#if  (FEATURE_MODE == 0)
/**
 @file ctc_usw_ptp.c

 @date 2010-6-7

 @version v2.0

  This file contains PTP sys layer function implementation
*/

/****************************************************************************
 *
* Header Files
*
****************************************************************************/
#include "sal.h"
#include "ctc_ptp.h"         /* ctc layer PTP ds */
#include "ctc_error.h"
#include "ctc_debug.h"
#include "ctc_warmboot.h"

#include "sys_usw_ptp.h"  /* sys ds for all PTP sub modules */
#include "sys_usw_common.h"
#include "sys_usw_wb_common.h"
#include "sys_usw_interrupt.h"
#include "sys_usw_register.h"
#include "sys_usw_packet.h"
#include "sys_usw_dmps.h"
#include "sys_usw_eunit.h"
#include "sys_usw_mac.h"
#include "sys_usw_flexe.h"
#include "drv_api.h"
/****************************************************************************
 *
* Defines and Macros
*
*****************************************************************************/
#define SYS_PTP_MAX_SYNC_CLOCK_FREQUENCY_HZ (25000000)

#define SYS_PTP_TOD_MESSAGE_LENTH     128

#define SYS_PTP_MAX_TX_TS_BLOCK_NUM  4
#define SYS_PTP_MAX_TX_TS_BLOCK_SIZE  SYS_PHY_PORT_NUM_PER_SLICE
#define SYS_PTP_MAX_RX_TS_BLOCK_NUM  2
#define SYS_PTP_MAX_RX_TS_BLOCK_SIZE  MCHIP_CAP(SYS_CAP_PTP_CAPTURED_RX_SEQ_ID)


#define SYS_PTP_TIEM_INTF_SYNCE_0 0
#define SYS_PTP_TIEM_INTF_SYNCE_1 1
#define SYS_PTP_TIEM_INTF_SERDES 4
#define SYS_PTP_TIEM_INTF_SYNC_PULSE 5
#define SYS_PTP_TIEM_INTF_TOD_1PPS 6
#define SYS_PTP_TIEM_INTF_GPIO_0 7
#define SYS_PTP_TIEM_INTF_GPIO_1 8

#define SYS_PTP_MSG_TYPE_SYNC        0
#define SYS_PTP_MSG_TYPE_DELAY_REQ   1
#define SYS_PTP_MSG_TYPE_PDELAY_REQ  2
#define SYS_PTP_MSG_TYPE_PDELAY_RESP 3

/* clock id */
#define SYS_PTP_DEFAULT_CLOCK_ID    0
#define SYS_PTP_RESERVED_CLOCK_ID   1
#define SYS_PTP_USER_CLOCK_ID_MIN   2
#define SYS_PTP_USER_CLOCK_ID_MAX   7
#define SYS_PTP_MAX_DRIFT_RATE 0x3FFFFFFF
#define SYS_PTP_MAX_DRIFT_TIME 18  /*18s*/

#define M_UNTT_MISC      6
#define M_UNTT_FLAG_CODE_READY   0
#define M_UNTT_FLAG_FLEX_ENABLE  1

#define SYS_PTP_CS_TXQM_NUM_START 2

#define SYS_PTP_SYNC_INTF_HW_MODE_BIT  31


/****************************************************************************
*
* Data structures
*
****************************************************************************/
/**
 @brief   ptp captured timestamp
*/
struct sys_ptp_capured_ts_s
{
    uint16  lport_or_source;     /*save captured source or lport*/
    uint8  resv;
    uint16 seq_id;            /**< sequence ID*/
    uint32 system_time;
    ctc_ptp_time_t ts;
};
typedef struct sys_ptp_capured_ts_s sys_ptp_capured_ts_t;

/****************************************************************************
 *
* Global and Declaration
*
*****************************************************************************/
 sys_ptp_master_t* p_usw_ptp_master[CTC_MAX_LOCAL_CHIP_NUM_PP] = {NULL};
 sal_mutex_t*   p_ptp_cb_mutex = NULL;

/****************************************************************************
 *
* Function
*
*****************************************************************************/
STATIC int32
_sys_usw_ptp_set_sync_intf_toggle_time(uint8 lchip, ctc_ptp_time_t* p_toggle_time);


#define __1_PTP_COMMON__
STATIC int32
_sys_usw_ptp_check_ptp_eunit_init(uint8 lchip, uint32* value)
{
    uint32 cmd = 0;
    McpuMiscIntInfo0_m misc_info;

    cmd = DRV_IOR(McpuMiscIntInfo0_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, M_UNTT_MISC, cmd, &misc_info));
    *value = GetMcpuMiscIntInfo0(V,miscIntInfo0_f, &misc_info);

    return CTC_E_NONE;
}

STATIC int32
_sys_usw_ptp_check_ptp_init(uint8 lchip)
{
    uint32 cmd = 0;
    int32 ret = CTC_E_NONE;
    TsEngineRefRcCtl_m ptp_frc_ctl;

    /* check ptp ref rc clock, if not exist, read will fail */
    cmd = DRV_IOR(TsEngineRefRcCtl_t, DRV_ENTRY_FLAG);
    ret = DRV_IOCTL(lchip, 0, cmd, &ptp_frc_ctl);

    return ret;
}

STATIC int32
_sys_usw_ptp_get_quanta(uint8 lchip, uint8* quanta)
{
    *quanta = MCHIP_CAP(SYS_CAP_PTP_RC_QUANTA);

    return CTC_E_NONE;
}

uint8 at_ctc2sys_capture_type[]=
{
    SYS_AT_PTP_TIEM_INTF_GPIO_0,
    SYS_AT_PTP_TIEM_INTF_GPIO_1,
    SYS_AT_PTP_TIEM_INTF_NONE,
    SYS_AT_PTP_TIEM_INTF_NONE,
    SYS_AT_PTP_TIEM_INTF_NONE,
    SYS_AT_PTP_TIEM_INTF_SYNC_PULSE_0,
    SYS_AT_PTP_TIEM_INTF_TOD_1PPS,
    SYS_AT_PTP_TIEM_INTF_SYNC_PULSE_1,
    SYS_AT_PTP_TIEM_INTF_NONE
};

uint8 at_sys2ctc_capture_type[]=
{
    CTC_PTP_TIEM_INTF_GPIO_0,
    CTC_PTP_TIEM_INTF_GPIO_1,
    CTC_PTP_TIEM_INTF_SYNC_PULSE,
    CTC_PTP_TIEM_INTF_SYNC_PULSE_1,
    CTC_PTP_TIEM_INTF_TOD_1PPS,
    MAX_CTC_PTP_TIEM_INTF,
    MAX_CTC_PTP_TIEM_INTF,
    MAX_CTC_PTP_TIEM_INTF,
    MAX_CTC_PTP_TIEM_INTF,
    MAX_CTC_PTP_TIEM_INTF
};


STATIC int32
_sys_usw_ptp_map_captured_src(uint8 lchip, ctc_ptp_captured_src_t* ctc_src_type, uint8* sys_src_type, uint8 is_ctc2sys)
{
    if (is_ctc2sys)
    {
        if (DRV_FROM_AT(lchip))
        {
            if (at_ctc2sys_capture_type[*ctc_src_type] == SYS_AT_PTP_TIEM_INTF_NONE)
            {
                return CTC_E_INVALID_PARAM;
            }
            *sys_src_type = at_ctc2sys_capture_type[*ctc_src_type];
            return CTC_E_NONE;
        }
        switch (*ctc_src_type)
        {
            case CTC_PTP_TIEM_INTF_GPIO_0:
                *sys_src_type = SYS_PTP_TIEM_INTF_GPIO_0;
                break;

            case CTC_PTP_TIEM_INTF_GPIO_1:
                *sys_src_type = SYS_PTP_TIEM_INTF_GPIO_1;
                break;

            case CTC_PTP_TIEM_INTF_SYNCE_0:
                *sys_src_type = SYS_PTP_TIEM_INTF_SYNCE_0;
                break;

            case CTC_PTP_TIEM_INTF_SYNCE_1:
                *sys_src_type = SYS_PTP_TIEM_INTF_SYNCE_1;
                break;

            case CTC_PTP_TIEM_INTF_SERDES:
                *sys_src_type = SYS_PTP_TIEM_INTF_SERDES;
                break;

            case CTC_PTP_TIEM_INTF_SYNC_PULSE:
                *sys_src_type = SYS_PTP_TIEM_INTF_SYNC_PULSE;
                break;

            case CTC_PTP_TIEM_INTF_TOD_1PPS:
                *sys_src_type = SYS_PTP_TIEM_INTF_TOD_1PPS;
                break;

            default:
                return CTC_E_INVALID_PARAM;
        }
    }
    else
    {

        if (DRV_FROM_AT(lchip))
        {
            if (at_sys2ctc_capture_type[*sys_src_type] == MAX_CTC_PTP_TIEM_INTF)
            {
                return CTC_E_INVALID_PARAM;
            }
            *ctc_src_type = at_sys2ctc_capture_type[*sys_src_type];
            return CTC_E_NONE;
        }
        switch (*sys_src_type)
        {
            case SYS_PTP_TIEM_INTF_GPIO_0:
                *ctc_src_type = CTC_PTP_TIEM_INTF_GPIO_0;
                break;

            case SYS_PTP_TIEM_INTF_GPIO_1:
                *ctc_src_type = CTC_PTP_TIEM_INTF_GPIO_1;
                break;

            case SYS_PTP_TIEM_INTF_SYNCE_0:
                *ctc_src_type = CTC_PTP_TIEM_INTF_SYNCE_0;
                break;

            case SYS_PTP_TIEM_INTF_SYNCE_1:
                *ctc_src_type = CTC_PTP_TIEM_INTF_SYNCE_1;
                break;

            case SYS_PTP_TIEM_INTF_SERDES:
                *ctc_src_type = CTC_PTP_TIEM_INTF_SERDES;
                break;

            case SYS_PTP_TIEM_INTF_SYNC_PULSE:
                *ctc_src_type = CTC_PTP_TIEM_INTF_SYNC_PULSE;
                break;

            case SYS_PTP_TIEM_INTF_TOD_1PPS:
                *ctc_src_type = CTC_PTP_TIEM_INTF_TOD_1PPS;
                break;

            default:
                return CTC_E_INVALID_PARAM;
        }
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_usw_ptp_free_node_data(void* node_data, void* user_data)
{
    mem_free(node_data);

    return CTC_E_NONE;
}

STATIC uint8 
_sys_usw_ptp_caculate_tod_crc(uint8* data, uint32 len)
{
    uint8 old_crc[8];
    uint8 i = 0;
    uint8 bit[8];
    uint8 crc[8];
    uint8 new_crc = 0;
    uint32 cnt = 0;

    sal_memset(old_crc, 0x1, 8);

    /*tod always send low bits first, must change data order first, return crc must change order too*/
    for(cnt = 0; cnt < len; cnt++)
    {
        for(i = 0; i < 8; i++)
        {
            bit[7-i] = (data[cnt]>>i)&1;
        }

        for(i = 0; i < 8; i++)
        {
            bit[i] = bit[i] ^ old_crc[i];
        }

        crc[7] = bit[5] ^ bit[3] ^ bit[2];
        crc[6] = bit[7] ^ bit[4] ^ bit[2] ^ bit[1];
        crc[5] = bit[7] ^ bit[6] ^ bit[3] ^ bit[1] ^ bit[0];
        crc[4] = bit[7] ^ bit[6] ^ bit[3] ^ bit[0];
        crc[3] = bit[7] ^ bit[6] ^ bit[3];
        crc[2] = bit[6] ^ bit[5] ^ bit[2];
        crc[1] = bit[7] ^ bit[5] ^ bit[4] ^ bit[1];
        crc[0] = bit[6] ^ bit[4] ^ bit[3] ^ bit[0];
        for(i = 0; i < 8; i++)
        {
            old_crc[i] = crc[i];
        }
    }

    new_crc = (old_crc[7])|(old_crc[6]<<1)|(old_crc[5]<<2)|(old_crc[4]<<3)|(old_crc[3]<<4)|(old_crc[2]<<5)|(old_crc[1]<<6)|(old_crc[0]<<7);
    return new_crc;
}

#define __2_PTP_TS_WB__
STATIC int32
_sys_usw_ptp_wb_sync(uint8 lchip, uint32 app_id)
{
    int32 ret = CTC_E_NONE;
    ctc_wb_data_t wb_data = {0};
    sys_wb_ptp_master_t* p_wb_ptp_master = NULL;
    sys_wb_ptp_session_info_t* p_wb_ptp_session = NULL;
    uint32 index = 0;

    if (NULL == p_usw_ptp_master[lchip])
    {
        return CTC_E_NONE;
    }

    /*syncup buffer*/
    CTC_WB_ALLOC_BUFFER(&wb_data.buffer);
    PTP_LOCK;
    if (app_id == 0 || CTC_WB_SUBID(app_id) == SYS_WB_APPID_PTP_SUBID_MASTER)
    {
        /*syncup statsid*/
        CTC_WB_INIT_DATA_T((&wb_data), sys_wb_ptp_master_t, CTC_FEATURE_PTP, SYS_WB_APPID_PTP_SUBID_MASTER);

        p_wb_ptp_master = (sys_wb_ptp_master_t *)wb_data.buffer;

        p_wb_ptp_master->lchip = lchip;
        p_wb_ptp_master->version = SYS_WB_VERSION_PTP;
        p_wb_ptp_master->quanta = p_usw_ptp_master[lchip]->quanta;
        p_wb_ptp_master->intf_selected = p_usw_ptp_master[lchip]->intf_selected;
        p_wb_ptp_master->cache_aging_time = p_usw_ptp_master[lchip]->cache_aging_time;
        p_wb_ptp_master->drift_nanoseconds = p_usw_ptp_master[lchip]->drift_nanoseconds;
        p_wb_ptp_master->tod_1pps_flex_en = p_usw_ptp_master[lchip]->tod_1pps_flex_en;
        p_wb_ptp_master->tod_1pps_mode = p_usw_ptp_master[lchip]->tod_1pps_mode;
        p_wb_ptp_master->tod_1pps_thrd = p_usw_ptp_master[lchip]->tod_1pps_thrd;
        p_wb_ptp_master->rsv = 0;
        switch (p_usw_ptp_master[lchip]->device_type)
        {
            case CTC_PTP_DEVICE_NONE:
                {
                    p_wb_ptp_master->device_type = SYS_WB_PTP_DEVICE_NONE;
                    break;
                }
            case CTC_PTP_DEVICE_OC:
                {
                    p_wb_ptp_master->device_type = SYS_WB_PTP_DEVICE_OC;
                    break;
                }
            case CTC_PTP_DEVICE_BC:
                {
                    p_wb_ptp_master->device_type = SYS_WB_PTP_DEVICE_BC;
                    break;
                }
            case CTC_PTP_DEVICE_E2E_TC:
                {
                    p_wb_ptp_master->device_type = SYS_WB_PTP_DEVICE_E2E_TC;
                    break;
                }
            case CTC_PTP_DEVICE_P2P_TC:
                {
                    p_wb_ptp_master->device_type = SYS_WB_PTP_DEVICE_P2P_TC;
                    break;
                }
            default:
                {
                    p_wb_ptp_master->device_type = SYS_WB_PTP_DEVICE_NONE;
                    break;
                }
        }
        p_wb_ptp_master->tod_1pps_duty = p_usw_ptp_master[lchip]->tod_1pps_duty;
        p_wb_ptp_master->tod_1pps_delay = p_usw_ptp_master[lchip]->tod_1pps_delay;
        p_wb_ptp_master->tod_1pps_delay_nano_ns = p_usw_ptp_master[lchip]->tod_1pps_delay_nano_ns;

        if (DRV_FROM_AT(lchip))
        {
            p_wb_ptp_master->ptp_opf_type = p_usw_ptp_master[lchip]->ptp_opf_type;
            sal_memcpy(p_wb_ptp_master->session_en_bmp,p_usw_ptp_master[lchip]->session_en_bmp, sizeof(p_wb_ptp_master->session_en_bmp));
        }

        wb_data.valid_cnt = 1;
        CTC_ERROR_GOTO(ctc_wb_add_entry(&wb_data), ret, done);
        CTC_WB_SYNC_END_DATA(CTC_FEATURE_PTP, SYS_WB_APPID_PTP_SUBID_MASTER);

        if (DRV_FROM_AT(lchip))
        {
            if (app_id == 0 || CTC_WB_SUBID(app_id) == SYS_WB_APPID_PTP_SUBID_SESSION)
            {
                CTC_WB_INIT_DATA_T((&wb_data), sys_wb_ptp_session_info_t, CTC_FEATURE_PTP, SYS_WB_APPID_PTP_SUBID_SESSION);

                for(index = 0; index < SYS_PTP_MAX_SESSION_NUM; index++)
                {
                    p_wb_ptp_session = (sys_wb_ptp_session_info_t *)wb_data.buffer + index;
                    p_wb_ptp_session->index = index;
                    sal_memcpy(&p_wb_ptp_session->session,&p_usw_ptp_master[lchip]->session[index],sizeof(sys_ptp_session_t));
                }
            }
            wb_data.valid_cnt = SYS_PTP_MAX_SESSION_NUM;
            CTC_ERROR_GOTO(ctc_wb_add_entry(&wb_data), ret, done);
            CTC_WB_SYNC_END_DATA(CTC_FEATURE_PTP, SYS_WB_APPID_PTP_SUBID_SESSION);
        }
    }

    done:
    PTP_UNLOCK;
    CTC_WB_FREE_BUFFER(wb_data.buffer);

    return ret;
}

STATIC int32
_sys_usw_ptp_wb_restore(uint8 lchip)
{
    int32 ret = CTC_E_NONE;
    uint32 value = 0;
	uint32 session_bmp_array[4]= {0};

    ctc_wb_query_t wb_query;
    sys_wb_ptp_master_t wb_ptp_master;
    sys_wb_ptp_session_info_t wb_ptp_session;
    sys_usw_opf_t opf;
    uint32 entry_cnt = 0;
    uint8 index = 0;
    uint8 domain_id = 0;

    CTC_WB_ALLOC_BUFFER(&wb_query.buffer);
    PTP_LOCK;

    CTC_WB_INIT_QUERY_T((&wb_query), sys_wb_ptp_master_t, CTC_FEATURE_PTP, SYS_WB_APPID_PTP_SUBID_MASTER);

    sal_memset(&wb_ptp_master, 0, sizeof(sys_wb_ptp_master_t));

    CTC_ERROR_GOTO(ctc_wb_query_entry(&wb_query), ret, done);
    if ((wb_query.valid_cnt != 1) || (wb_query.is_end != 1))
    {
        CTC_WB_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "query ptp master error! valid_cnt: %d, is_end: %d.\n", wb_query.valid_cnt, wb_query.is_end);
        ret = CTC_E_NONE;
        goto done;
    }

    sal_memcpy((uint8 *)&wb_ptp_master, (uint8 *)wb_query.buffer, wb_query.key_len + wb_query.data_len);

    if (CTC_WB_VERSION_CHECK(SYS_WB_VERSION_PTP, wb_ptp_master.version))
    {
        CTC_ERROR_GOTO(CTC_E_VERSION_MISMATCH, ret, done);
    }

    p_usw_ptp_master[lchip]->quanta = wb_ptp_master.quanta;
    p_usw_ptp_master[lchip]->intf_selected = wb_ptp_master.intf_selected;
    p_usw_ptp_master[lchip]->cache_aging_time = wb_ptp_master.cache_aging_time;
    p_usw_ptp_master[lchip]->drift_nanoseconds = wb_ptp_master.drift_nanoseconds;
    p_usw_ptp_master[lchip]->tod_1pps_flex_en = wb_ptp_master.tod_1pps_flex_en;
    p_usw_ptp_master[lchip]->tod_1pps_mode = wb_ptp_master.tod_1pps_mode;
    p_usw_ptp_master[lchip]->tod_1pps_thrd = wb_ptp_master.tod_1pps_thrd;

    if (MCHIP_EUNIT(lchip) && MCHIP_EUNIT(lchip)->mcpu_get_config)
    {
        CTC_ERROR_GOTO(MCHIP_EUNIT(lchip)->mcpu_get_config(lchip, 0, &value), ret, done);
    }
    p_usw_ptp_master[lchip]->hw_mode = ((value >> SYS_PTP_SYNC_INTF_HW_MODE_BIT) & 0x1);
    switch (wb_ptp_master.device_type)
    {
        case SYS_WB_PTP_DEVICE_NONE:
        {
            p_usw_ptp_master[lchip]->device_type = CTC_PTP_DEVICE_NONE;
            break;
        }
        case SYS_WB_PTP_DEVICE_OC:
        {
            p_usw_ptp_master[lchip]->device_type = CTC_PTP_DEVICE_OC;
            break;
        }
        case SYS_WB_PTP_DEVICE_BC:
        {
            p_usw_ptp_master[lchip]->device_type = CTC_PTP_DEVICE_BC;
            break;
        }
        case SYS_WB_PTP_DEVICE_E2E_TC:
        {
            p_usw_ptp_master[lchip]->device_type = CTC_PTP_DEVICE_E2E_TC;
            break;
        }
        case SYS_WB_PTP_DEVICE_P2P_TC:
        {
            p_usw_ptp_master[lchip]->device_type = CTC_PTP_DEVICE_P2P_TC;
            break;
        }
        default:
        {
            p_usw_ptp_master[lchip]->device_type = CTC_PTP_DEVICE_NONE;
            break;
        }
    }

    p_usw_ptp_master[lchip]->tod_1pps_duty = wb_ptp_master.tod_1pps_duty;
    p_usw_ptp_master[lchip]->tod_1pps_delay = wb_ptp_master.tod_1pps_delay;
    p_usw_ptp_master[lchip]->tod_1pps_delay_nano_ns = wb_ptp_master.tod_1pps_delay_nano_ns;
    
    if (DRV_FROM_AT(lchip))
    {
        sal_memcpy(p_usw_ptp_master[lchip]->session_en_bmp, wb_ptp_master.session_en_bmp, sizeof(wb_ptp_master.session_en_bmp));
		sal_memcpy(session_bmp_array, wb_ptp_master.session_en_bmp, sizeof(wb_ptp_master.session_en_bmp));
		

        sal_memset(&opf, 0, sizeof(sys_usw_opf_t));
        p_usw_ptp_master[lchip]->ptp_opf_type = wb_ptp_master.ptp_opf_type;
        opf.pool_type = p_usw_ptp_master[lchip]->ptp_opf_type;

        CTC_WB_INIT_QUERY_T((&wb_query), sys_wb_ptp_session_info_t, CTC_FEATURE_PTP, SYS_WB_APPID_PTP_SUBID_SESSION);
        sal_memset(&wb_ptp_session, 0, sizeof(sys_wb_ptp_session_info_t));
        CTC_WB_QUERY_ENTRY_BEGIN((&wb_query));
        sal_memcpy(&wb_ptp_session, (sys_wb_ptp_session_info_t *)wb_query.buffer + entry_cnt,  wb_query.key_len + wb_query.data_len);
        sal_memcpy(&p_usw_ptp_master[lchip]->session[entry_cnt], &wb_ptp_session.session,sizeof(sys_ptp_session_t));
        entry_cnt++;
        CTC_WB_QUERY_ENTRY_END((&wb_query));

        for (index = 0; index < SYS_PTP_SESSION_NUM_PER_DOMAIN; index++)
        {
            for (domain_id = 0; domain_id <= MCHIP_CAP(SYS_CAP_PTP_MAX_DOMAIN_ID); domain_id++)
            {
                opf.pool_index = domain_id;
                if (CTC_BMP_ISSET(session_bmp_array + domain_id*(CTC_UINT64_BITS/CTC_UINT32_BITS), index))
                {
                    CTC_ERROR_GOTO(sys_usw_opf_alloc_offset_from_position(lchip, &opf, 1, index), ret, done);
                }
            }
        }
    }
done:
    PTP_UNLOCK;
    CTC_WB_FREE_BUFFER(wb_query.buffer);

    return ret;
}

STATIC int32
_sys_usw_ptp_wb_init(uint8 lchip)
{
   ctc_wb_appid_t  appid;
   sal_memset(&appid,0,sizeof(appid));

   appid.app_id = lchip << 16 | CTC_WB_APPID(CTC_FEATURE_PTP, SYS_WB_APPID_PTP_SUBID_MASTER) ;
   appid.entry_num = 1;
   appid.entry_size  = sizeof(sys_wb_ptp_master_t);
   appid.rt_en = 0;
   ctc_wb_add_appid( lchip, &appid);

   appid.app_id = lchip << 16 | CTC_WB_APPID(CTC_FEATURE_PTP, SYS_WB_APPID_PTP_SUBID_SESSION) ;
   appid.entry_num = SYS_PTP_MAX_SESSION_NUM;
   appid.entry_size  = sizeof(sys_wb_ptp_session_info_t);
   appid.rt_en = 0;
   ctc_wb_add_appid( lchip, &appid);

   return CTC_E_NONE;
}

#define __3_PTP_TS_CACHE__
STATIC int32
_sys_usw_ptp_add_ts_cache(uint8 lchip, ctc_ptp_captured_type_t type, sys_ptp_capured_ts_t* p_captured_ts)
{
    int32 ret = CTC_E_NONE;
    uint32 index = 0;
    sal_systime_t systime;
    sys_ptp_capured_ts_t* p_ts_node = NULL;
    sys_ptp_capured_ts_t* p_ts_node_get = NULL;
    bool add_cache = TRUE;
    uint8 gchip = 0;
    sys_usw_dmps_port_info_t dmps_port_info = {0};

    /*get systime*/
    sal_gettime(&systime);

    p_ts_node = (sys_ptp_capured_ts_t*)mem_malloc(MEM_PTP_MODULE, sizeof(sys_ptp_capured_ts_t));
    if (NULL == p_ts_node)
    {
        SYS_PTP_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " No memory \n");
        return CTC_E_NO_MEMORY;
    }

    sal_memcpy(p_ts_node, p_captured_ts, sizeof(sys_ptp_capured_ts_t));
    p_ts_node->system_time = systime.tv_sec;

    if (CTC_PTP_CAPTURED_TYPE_RX == type)
    {
        index = (p_ts_node->lport_or_source % MAX_CTC_PTP_TIEM_INTF) * SYS_PTP_MAX_RX_TS_BLOCK_SIZE + p_ts_node->seq_id;
        p_ts_node_get = (sys_ptp_capured_ts_t*)ctc_vector_get(p_usw_ptp_master[lchip]->p_rx_ts_vector, index);
        if (p_ts_node_get != NULL)
        {
            ctc_vector_del(p_usw_ptp_master[lchip]->p_rx_ts_vector, index);
            mem_free(p_ts_node_get);
        }

        add_cache = ctc_vector_add(p_usw_ptp_master[lchip]->p_rx_ts_vector, index, p_ts_node);
        if (!add_cache)
        {
            mem_free(p_ts_node);
            ret = CTC_E_NO_MEMORY;
        }
    }
    else if (CTC_PTP_CAPTURED_TYPE_TX == type)
    {
        uint32 mac_id = 0;
        CTC_ERROR_GOTO(sys_usw_get_gchip_id(lchip, &gchip), ret, error_proc);
        dmps_port_info.gport = CTC_MAP_LPORT_TO_GPORT(gchip, p_ts_node->lport_or_source);
        CTC_ERROR_RETURN(sys_usw_port_api_get_dmps_property(lchip, &dmps_port_info, SYS_PORT_API_DMPS_PROP_MAC_ID, &mac_id));
        index = p_ts_node->seq_id * SYS_PTP_MAX_TX_TS_BLOCK_SIZE + mac_id;
        p_ts_node_get = (sys_ptp_capured_ts_t*)ctc_vector_get(p_usw_ptp_master[lchip]->p_tx_ts_vector, index);
        if (p_ts_node_get != NULL)
        {
            ctc_vector_del(p_usw_ptp_master[lchip]->p_tx_ts_vector, index);
            mem_free(p_ts_node_get);
        }

        add_cache = ctc_vector_add(p_usw_ptp_master[lchip]->p_tx_ts_vector, index, p_ts_node);
        if (!add_cache)
        {
            mem_free(p_ts_node);
            ret = CTC_E_NO_MEMORY;
        }
    }
    else
    {
        mem_free(p_ts_node);
        ret = CTC_E_INVALID_PARAM;
    }

    return ret;

error_proc:
    mem_free(p_ts_node);
    return ret;
}

STATIC int32
_sys_usw_ptp_get_ts_cache(uint8 lchip, ctc_ptp_captured_type_t type, sys_ptp_capured_ts_t* p_captured_ts)
{
    int32 ret = CTC_E_NONE;
    uint32 index = 0;
    sal_systime_t systime;
    sys_ptp_capured_ts_t* p_ts_node = NULL;
    uint8 gchip = 0;
    sys_usw_dmps_port_info_t dmps_port_info = {0};

    /*get systime*/
    sal_gettime(&systime);

    if (CTC_PTP_CAPTURED_TYPE_RX == type)
    {
        index = (p_captured_ts->lport_or_source % MAX_CTC_PTP_TIEM_INTF) * SYS_PTP_MAX_RX_TS_BLOCK_SIZE + p_captured_ts->seq_id;
        p_ts_node = (sys_ptp_capured_ts_t*)ctc_vector_get(p_usw_ptp_master[lchip]->p_rx_ts_vector, index);
        if (NULL == p_ts_node)
        {
            return CTC_E_INVALID_CONFIG;
        }

        sal_memcpy(p_captured_ts, p_ts_node, sizeof(sys_ptp_capured_ts_t));
    }
    else if (CTC_PTP_CAPTURED_TYPE_TX == type)
    {
        uint32 mac_id = 0;
        CTC_ERROR_GOTO(sys_usw_get_gchip_id(lchip, &gchip), ret, error_proc);
        dmps_port_info.gport = CTC_MAP_LPORT_TO_GPORT(gchip, p_captured_ts->lport_or_source);
        CTC_ERROR_RETURN(sys_usw_port_api_get_dmps_property(lchip, &dmps_port_info, SYS_PORT_API_DMPS_PROP_MAC_ID, &mac_id));
        index = p_captured_ts->seq_id * SYS_PTP_MAX_TX_TS_BLOCK_SIZE + mac_id;
        p_ts_node = (sys_ptp_capured_ts_t*)ctc_vector_get(p_usw_ptp_master[lchip]->p_tx_ts_vector, index);
        if (NULL == p_ts_node)
        {
            return CTC_E_INVALID_CONFIG;
        }

        sal_memcpy(p_captured_ts, p_ts_node, sizeof(sys_ptp_capured_ts_t));
    }
    else
    {
        return CTC_E_INVALID_PARAM;
    }

    /* the ts get form cache has already time out*/
    if ((systime.tv_sec - p_captured_ts->system_time) >= p_usw_ptp_master[lchip]->cache_aging_time)
    {
        return CTC_E_INVALID_CONFIG;
    }

    return CTC_E_NONE;

error_proc:
    return ret;
}

#define __4_PTP_FUNC__
STATIC int32
_sys_usw_ptp_set_cache_aging_time(uint8 lchip, uint32 value)
{
    p_usw_ptp_master[lchip]->cache_aging_time = value;

    return CTC_E_NONE;
}

STATIC int32
_sys_usw_ptp_get_cache_aging_time(uint8 lchip, uint32 *value)
{
    *value = p_usw_ptp_master[lchip]->cache_aging_time;

    return CTC_E_NONE;
}

STATIC int32
_sys_usw_ptp_set_sync_of_tod_input_select(uint8 lchip, uint32 value)
{
    uint32 cmd = 0;
    uint32 field_sync_value = 0;
    uint32 field_tod_value = 0;

    switch (value)
    {
        case CTC_PTP_INTF_SELECT_NONE:
        {
            field_sync_value = 0;
            cmd = DRV_IOW(TsEngineSyncIntfCfg_t, TsEngineSyncIntfCfg_tsCaptureEn_f);
            CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &field_sync_value));

            field_tod_value = 0;
            cmd = DRV_IOW(TsEngineTodCfg_t, TsEngineTodCfg_todTsCaptureEn_f);
            CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &field_tod_value));
            break;
        }
        case CTC_PTP_INTF_SELECT_SYNC:
        {
            field_tod_value = 0;
            cmd = DRV_IOW(TsEngineTodCfg_t, TsEngineTodCfg_todTsCaptureEn_f);
            CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &field_tod_value));

            field_sync_value = 1;
            cmd = DRV_IOW(TsEngineSyncIntfCfg_t, TsEngineSyncIntfCfg_tsCaptureEn_f);
            CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &field_sync_value));
            break;
        }
        case CTC_PTP_INTF_SELECT_TOD:
        {
            field_sync_value = 0;
            cmd = DRV_IOW(TsEngineSyncIntfCfg_t, TsEngineSyncIntfCfg_tsCaptureEn_f);
            CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &field_sync_value));

            field_tod_value = 1;
            cmd = DRV_IOW(TsEngineTodCfg_t, TsEngineTodCfg_todTsCaptureEn_f);
            CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &field_tod_value));
            break;
        }
        default:
        {
            return CTC_E_INVALID_PARAM;
        }
    }

    p_usw_ptp_master[lchip]->intf_selected = value;

    return CTC_E_NONE;
}

STATIC int32
_sys_usw_ptp_get_sync_of_tod_input_select(uint8 lchip, uint32 *value)
{
    *value = p_usw_ptp_master[lchip]->intf_selected;

    return CTC_E_NONE;
}

STATIC int32
_sys_usw_ptp_get_frc_timestamp(uint8 lchip, ctc_ptp_time_t* timestamp)
{
    uint32 cmd = 0;
    uint32 rc_s = 0;
    uint32 rc_ns = 0;
    uint32 rc_nns = 0;
    TsEngineRefRc_m ptp_ref_frc;

    /*read frc time*/
    sal_memset(&ptp_ref_frc, 0, sizeof(ptp_ref_frc));

    SYS_EUNIT_HW_LOCK(lchip, SYS_EUNIT_M, 0);
    cmd = DRV_IOR(TsEngineRefRc_t, DRV_ENTRY_FLAG);
    DRV_IOCTL(lchip, 0, cmd, &ptp_ref_frc);
    SYS_EUNIT_HW_UNLOCK(lchip, SYS_EUNIT_M, 0);
    GetTsEngineRefRc(A, rcSecond_f, &ptp_ref_frc, &rc_s);
    GetTsEngineRefRc(A, rcNs_f, &ptp_ref_frc, &rc_ns);
    GetTsEngineRefRc(A, rcFracNs_f, &ptp_ref_frc, &rc_nns);

    timestamp->seconds = rc_s ;
    timestamp->nanoseconds = rc_ns;
    timestamp->nano_nanoseconds = rc_nns;

    return CTC_E_NONE;
}

STATIC int32
_sys_usw_ptp_get_clock_timestamp(uint8 lchip, ctc_ptp_time_t* timestamp)
{
    int32 ret = CTC_E_NONE;
    uint32 cmd = 0;
    uint32 offset_ns = 0;
    uint32 offset_s = 0;
    uint32 rc_s = 0;
    uint32 rc_ns = 0;
    uint32 rc_nns = 0;
    TsEngineRefRc_m ptp_ref_frc;
    TsEngineOffsetAdj_m ptp_offset_adjust;

    /*read frc time*/

    SYS_EUNIT_HW_LOCK(lchip, SYS_EUNIT_M, 0);
    sal_memset(&ptp_ref_frc, 0, sizeof(ptp_ref_frc));
    cmd = DRV_IOR(TsEngineRefRc_t, DRV_ENTRY_FLAG);
    CTC_ERROR_GOTO(DRV_IOCTL(lchip, 0, cmd, &ptp_ref_frc), ret, out);

    sal_memset(&ptp_offset_adjust, 0, sizeof(ptp_offset_adjust));
    cmd = DRV_IOR(TsEngineOffsetAdj_t, DRV_ENTRY_FLAG);
    CTC_ERROR_GOTO(DRV_IOCTL(lchip, 0, cmd, &ptp_offset_adjust), ret, out);
    SYS_EUNIT_HW_UNLOCK(lchip, SYS_EUNIT_M, 0);

    GetTsEngineRefRc(A, rcSecond_f, &ptp_ref_frc, &rc_s);
    GetTsEngineRefRc(A, rcNs_f, &ptp_ref_frc, &rc_ns);
    GetTsEngineRefRc(A, rcFracNs_f, &ptp_ref_frc, &rc_nns);

    GetTsEngineOffsetAdj(A, offsetNs_f, &ptp_offset_adjust, &offset_ns);
    GetTsEngineOffsetAdj(A, offsetSecond_f, &ptp_offset_adjust, &offset_s);

    if ((rc_ns + offset_ns) >= MCHIP_CAP(SYS_CAP_PTP_NS_OR_NNS_VALUE))
    {
        timestamp->seconds = rc_s + offset_s + 1;
        timestamp->nanoseconds = rc_ns + offset_ns - MCHIP_CAP(SYS_CAP_PTP_NS_OR_NNS_VALUE);
        timestamp->nano_nanoseconds = rc_nns;
    }
    else
    {
        timestamp->seconds = rc_s + offset_s;
        timestamp->nanoseconds = rc_ns + offset_ns;
        timestamp->nano_nanoseconds = rc_nns;
    }

    timestamp->is_negative = 0;

    return CTC_E_NONE;

out:

    SYS_EUNIT_HW_UNLOCK(lchip, SYS_EUNIT_M, 0);
    return ret;
}

/**
 @brief Adjust offset for free running clock
*/
STATIC int32
_sys_usw_ptp_adjust_frc(uint8 lchip, ctc_ptp_time_t* offset)
{
    int32 ret = CTC_E_NONE;
    uint32 cmd = 0;
    uint32 offset_ns = 0;
    uint32 offset_s = 0;
    uint32 adj_ns = 0;
    uint32 adj_s = 0;
    TsEngineOffsetAdj_m ptp_offset_adjust;

    sal_memset(&ptp_offset_adjust, 0, sizeof(ptp_offset_adjust));
    SYS_EUNIT_HW_LOCK(lchip, SYS_EUNIT_M, 0);
    cmd = DRV_IOR(TsEngineOffsetAdj_t, DRV_ENTRY_FLAG);
    DRV_IOCTL(lchip, 0, cmd, &ptp_offset_adjust);
    SYS_EUNIT_HW_UNLOCK(lchip, SYS_EUNIT_M, 0);
    
    GetTsEngineOffsetAdj(A, offsetNs_f, &ptp_offset_adjust, &adj_ns);
    GetTsEngineOffsetAdj(A, offsetSecond_f, &ptp_offset_adjust, &adj_s);

    /*calculate adjust*/
    if (offset->is_negative)  /*offset = adjust - offset*/
    {
        if (adj_ns < offset->nanoseconds) /* not enough for minus */
        {
            offset_ns = adj_ns + MCHIP_CAP(SYS_CAP_PTP_NS_OR_NNS_VALUE) - offset->nanoseconds;
            if ((adj_s < offset->seconds) || (adj_s -offset->seconds < 1))
            {
                return CTC_E_INVALID_PARAM;
            }
            offset_s = adj_s - offset->seconds - 1;
        }
        else
        {
            offset_ns = adj_ns - offset->nanoseconds;
            if (adj_s < offset->seconds)
            {
                return CTC_E_INVALID_PARAM;
            }
            offset_s = adj_s - offset->seconds;
        }
    }
    else  /*offset = adjust + offset*/
    {
        if ((offset->nanoseconds + adj_ns) >= MCHIP_CAP(SYS_CAP_PTP_NS_OR_NNS_VALUE))
        {
            offset_ns = offset->nanoseconds + adj_ns - MCHIP_CAP(SYS_CAP_PTP_NS_OR_NNS_VALUE);
            offset_s = offset->seconds + adj_s + 1;
        }
        else
        {
            offset_ns = offset->nanoseconds + adj_ns;
            offset_s = offset->seconds + adj_s;
        }
    }

    SetTsEngineOffsetAdj(V, offsetNs_f, &ptp_offset_adjust, offset_ns);
    SetTsEngineOffsetAdj(V, offsetSecond_f, &ptp_offset_adjust, offset_s);
    CTC_ERROR_RETURN(sys_usw_packet_tx_set_property(lchip, SYS_PKT_TX_TYPE_PTP_ADJUST_OFFSET, offset_ns, offset_s));

    /*adjust frc offset*/

    SYS_EUNIT_HW_LOCK(lchip, SYS_EUNIT_M, 0);
    cmd = DRV_IOW(TsEngineOffsetAdj_t, DRV_ENTRY_FLAG);
    DRV_IOCTL(lchip, 0, cmd, &ptp_offset_adjust);
    SYS_EUNIT_HW_UNLOCK(lchip, SYS_EUNIT_M, 0);

    return ret;
}

STATIC int32
_sys_usw_ptp_adjust_clock_offset(uint8 lchip, ctc_ptp_time_t* offset)
{
    int32 ret = CTC_E_NONE;
    ctc_ptp_time_t offset_tmp;
    ctc_ptp_time_t time;
    uint8 offset_adjust_step = 0;
    uint8 offset_adjust_remainder = 0;
    uint8 offset_adjust_num = 0;
    uint8 i = 0;

    if(DRV_FROM_TM(lchip))
    {
        /* adjust offset */
        CTC_ERROR_GOTO(_sys_usw_ptp_adjust_frc(lchip, offset), ret, out);
        return CTC_E_NONE;
    }

    /*1. adjust clock offset*/
    if ((offset->seconds != 0) || (offset->nanoseconds > MCHIP_CAP(SYS_CAP_PTP_TOD_ADJUSTING_THRESHOLD))
        || (CTC_PTP_INTF_SELECT_SYNC == p_usw_ptp_master[lchip]->intf_selected))
    {
        /* adjust offset */
        CTC_ERROR_GOTO(_sys_usw_ptp_adjust_frc(lchip, offset), ret, out);

        if (CTC_PTP_INTF_SELECT_SYNC != p_usw_ptp_master[lchip]->intf_selected)
        {
            /* read time*/
            sal_memset(&time, 0, sizeof(time));
            CTC_ERROR_GOTO(_sys_usw_ptp_get_frc_timestamp(lchip, &time), ret, out);

            /* set toggle time*/
            if ((time.nanoseconds + MCHIP_CAP(SYS_CAP_PTP_TOD_ADJUSTING_TOGGLE_STEP)) >= MCHIP_CAP(SYS_CAP_PTP_NS_OR_NNS_VALUE))
            {
                time.seconds++;
                time.nanoseconds = time.nanoseconds + MCHIP_CAP(SYS_CAP_PTP_TOD_ADJUSTING_TOGGLE_STEP) - MCHIP_CAP(SYS_CAP_PTP_NS_OR_NNS_VALUE);
            }
            else
            {
                time.nanoseconds = time.nanoseconds + MCHIP_CAP(SYS_CAP_PTP_TOD_ADJUSTING_TOGGLE_STEP);
            }
            CTC_ERROR_GOTO(_sys_usw_ptp_set_sync_intf_toggle_time(lchip, &time), ret, out);
        }
    }
    else
    {
        offset_adjust_step = p_usw_ptp_master[lchip]->quanta - 1;
        offset_adjust_num = offset->nanoseconds / offset_adjust_step;
        offset_adjust_remainder = offset->nanoseconds % offset_adjust_step;

        sal_memset(&offset_tmp, 0, sizeof(offset_tmp));
        offset_tmp.is_negative = offset->is_negative;
        offset_tmp.seconds = 0;
        offset_tmp.nanoseconds = offset_adjust_step;

        for (i = 0; i < offset_adjust_num; i++)
        {
            CTC_ERROR_GOTO(_sys_usw_ptp_adjust_frc(lchip, &offset_tmp), ret, out);
        }

        offset_tmp.nanoseconds = offset_adjust_remainder;
        CTC_ERROR_GOTO(_sys_usw_ptp_adjust_frc(lchip, &offset_tmp), ret, out);
    }

    return CTC_E_NONE;

out:
    return ret;
}

STATIC int32
_sys_usw_ptp_set_clock_drift(uint8 lchip, ctc_ptp_time_t* p_drift)
{
    int32 ret = CTC_E_NONE;
    uint32 cmd = 0;
    uint64 drift_rate = 0;
    uint64 nanoseconds = 0;
    uint64 act_freq = 0;
    TsEngineRefDriftRateAdj_m ptp_drift_rate_adjust;

   /*debug info*/
    SYS_PTP_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    nanoseconds = p_drift->nanoseconds;

    /*(fo-fr)*quanta=ns fo:measured frequency, fr: reference frquency*/
    act_freq = p_drift->is_negative?(MCHIP_CAP(SYS_CAP_PTP_NS_OR_NNS_VALUE) + nanoseconds)/p_usw_ptp_master[lchip]->quanta \
                :(MCHIP_CAP(SYS_CAP_PTP_NS_OR_NNS_VALUE) - nanoseconds)/p_usw_ptp_master[lchip]->quanta;

    /*calculate drift rate,drift rate = ns * (max_drift_rate/fo)*/
    drift_rate = (uint64)nanoseconds *((uint64)SYS_PTP_MAX_DRIFT_RATE/act_freq);
    if (drift_rate > SYS_PTP_MAX_DRIFT_RATE)
    {
        ret = CTC_E_INVALID_PARAM;
        goto out;
    }

    sal_memset(&ptp_drift_rate_adjust, 0, sizeof(ptp_drift_rate_adjust));
    SetTsEngineRefDriftRateAdj(V, sign_f, &ptp_drift_rate_adjust, p_drift->is_negative ? 1 : 0);
    SetTsEngineRefDriftRateAdj(V, driftRate_f, &ptp_drift_rate_adjust, drift_rate & SYS_PTP_MAX_DRIFT_RATE);

    /*adjust frc drift */
    cmd = DRV_IOW(TsEngineRefDriftRateAdj_t, DRV_ENTRY_FLAG);
    CTC_ERROR_GOTO(DRV_IOCTL(lchip, 0, cmd, &ptp_drift_rate_adjust), ret, out);
    p_usw_ptp_master[lchip]->drift_nanoseconds = p_drift->is_negative << 31 | p_drift->nanoseconds;

    return CTC_E_NONE;

out:
    return ret;
}

STATIC int32
_sys_usw_ptp_get_clock_drift(uint8 lchip, ctc_ptp_time_t* p_drift)
{   
    /*calculate ns = quata*freq*dirft / (SYS_PTP_MAX_DRIFT_RATE*quanta-drift) */
    p_drift->is_negative = (p_usw_ptp_master[lchip]->drift_nanoseconds >> 31) & 0x1;
    p_drift->seconds = 0;
    p_drift->nanoseconds = p_usw_ptp_master[lchip]->drift_nanoseconds & 0x7fffffff;
    p_drift->nano_nanoseconds = 0;

    return CTC_E_NONE;
}

STATIC int32
_sys_usw_ptp_set_device_type(uint8 lchip, ctc_ptp_device_type_t device_type)
{
    int32 ret = CTC_E_NONE;
    uint32 cmd = 0;
    DsPtpProfile_m ptp_profile;

    sal_memset(&ptp_profile, 0, sizeof(ptp_profile));

    /*config device type*/
    switch (device_type)
    {
        case CTC_PTP_DEVICE_NONE:
        {
            break;
        }
        case CTC_PTP_DEVICE_OC:
        case CTC_PTP_DEVICE_BC:
        {
            SetDsPtpProfile(V, array_0_exceptionToCpu_f, &ptp_profile, 1); /*sync*/
            SetDsPtpProfile(V, array_0_discardPacket_f, &ptp_profile, 1);
            SetDsPtpProfile(V, array_0_applyIngressAsymmetryDelay_f, &ptp_profile, 1);
            SetDsPtpProfile(V, array_1_exceptionToCpu_f, &ptp_profile, 1); /*delay_req*/
            SetDsPtpProfile(V, array_1_discardPacket_f, &ptp_profile, 1);
            SetDsPtpProfile(V, array_1_applyEgressAsymmetryDelay_f, &ptp_profile, 1);
            SetDsPtpProfile(V, array_2_exceptionToCpu_f, &ptp_profile, 1); /*peer delay_req*/
            SetDsPtpProfile(V, array_2_discardPacket_f, &ptp_profile, 1);
            SetDsPtpProfile(V, array_2_applyEgressAsymmetryDelay_f, &ptp_profile, 1);
            SetDsPtpProfile(V, array_2_prevDiscardObeyException_f, &ptp_profile, 1);
            SetDsPtpProfile(V, array_3_exceptionToCpu_f, &ptp_profile, 1); /*peer delay_resp*/
            SetDsPtpProfile(V, array_3_discardPacket_f, &ptp_profile, 1);
            SetDsPtpProfile(V, array_3_applyIngressAsymmetryDelay_f, &ptp_profile, 1);
            SetDsPtpProfile(V, array_3_prevDiscardObeyException_f, &ptp_profile, 1);
            SetDsPtpProfile(V, array_8_exceptionToCpu_f, &ptp_profile, 1); /*follow_up*/
            SetDsPtpProfile(V, array_8_discardPacket_f, &ptp_profile, 1);
            SetDsPtpProfile(V, array_9_exceptionToCpu_f, &ptp_profile, 1); /*delay_resp*/
            SetDsPtpProfile(V, array_9_discardPacket_f, &ptp_profile, 1);
            SetDsPtpProfile(V, array_10_exceptionToCpu_f, &ptp_profile, 1); /*peer delay_resp_follow_up*/
            SetDsPtpProfile(V, array_10_discardPacket_f, &ptp_profile, 1);
            SetDsPtpProfile(V, array_10_prevDiscardObeyException_f, &ptp_profile, 1);
            SetDsPtpProfile(V, array_11_exceptionToCpu_f, &ptp_profile, 1); /*announce*/
            SetDsPtpProfile(V, array_11_discardPacket_f, &ptp_profile, 1);
            SetDsPtpProfile(V, array_12_exceptionToCpu_f, &ptp_profile, 1); /*signaling*/
            SetDsPtpProfile(V, array_12_discardPacket_f, &ptp_profile, 1);
            SetDsPtpProfile(V, array_13_exceptionToCpu_f, &ptp_profile, 1); /*management*/
            SetDsPtpProfile(V, array_13_discardPacket_f, &ptp_profile, 1);
            break;
        }
        case CTC_PTP_DEVICE_E2E_TC:
        {
            SetDsPtpProfile(V, array_0_updateResidenceTime_f, &ptp_profile, 1); /*sync*/
            SetDsPtpProfile(V, array_0_isCFlexUpdateResidenceTime_f, &ptp_profile, 1);
            SetDsPtpProfile(V, array_0_applyIngressAsymmetryDelay_f, &ptp_profile, 1);
            SetDsPtpProfile(V, array_1_updateResidenceTime_f, &ptp_profile, 1); /*delay_req*/
            SetDsPtpProfile(V, array_1_isCFlexUpdateResidenceTime_f, &ptp_profile, 1);
            SetDsPtpProfile(V, array_1_applyEgressAsymmetryDelay_f, &ptp_profile, 1);
            SetDsPtpProfile(V, array_2_discardPacket_f, &ptp_profile, 1); /*peer delay_req*/
            SetDsPtpProfile(V, array_3_discardPacket_f, &ptp_profile, 1); /*peer delay_resp*/
            SetDsPtpProfile(V, array_10_discardPacket_f, &ptp_profile, 1); /*peer delay_resp_follow_up*/
            break;
        }
        case CTC_PTP_DEVICE_P2P_TC:
        {
            SetDsPtpProfile(V, array_0_updateResidenceTime_f, &ptp_profile, 1); /*sync*/
            SetDsPtpProfile(V, array_0_isCFlexUpdateResidenceTime_f, &ptp_profile, 1);
            SetDsPtpProfile(V, array_0_applyIngressAsymmetryDelay_f, &ptp_profile, 1);
            SetDsPtpProfile(V, array_0_applyPathDelay_f, &ptp_profile, 1);
            SetDsPtpProfile(V, array_1_updateResidenceTime_f, &ptp_profile, 1); /*delay_req*/
            SetDsPtpProfile(V, array_1_isCFlexUpdateResidenceTime_f, &ptp_profile, 1);
            SetDsPtpProfile(V, array_1_applyEgressAsymmetryDelay_f, &ptp_profile, 1);
            SetDsPtpProfile(V, array_1_applyPathDelay_f, &ptp_profile, 1);
            SetDsPtpProfile(V, array_2_updateResidenceTime_f, &ptp_profile, 1); /*peer delay_req*/
            SetDsPtpProfile(V, array_2_isCFlexUpdateResidenceTime_f, &ptp_profile, 1);
            SetDsPtpProfile(V, array_2_applyEgressAsymmetryDelay_f, &ptp_profile, 1);
            SetDsPtpProfile(V, array_2_applyPathDelay_f, &ptp_profile, 1);
            SetDsPtpProfile(V, array_2_prevDiscardObeyException_f, &ptp_profile, 1);
            SetDsPtpProfile(V, array_2_exceptionToCpu_f, &ptp_profile, 1);
            SetDsPtpProfile(V, array_2_discardPacket_f, &ptp_profile, 1);
            SetDsPtpProfile(V, array_3_updateResidenceTime_f, &ptp_profile, 1); /*peer delay_resp*/
            SetDsPtpProfile(V, array_3_isCFlexUpdateResidenceTime_f, &ptp_profile, 1);
            SetDsPtpProfile(V, array_3_applyIngressAsymmetryDelay_f, &ptp_profile, 1);
            SetDsPtpProfile(V, array_3_applyPathDelay_f, &ptp_profile, 1);
            SetDsPtpProfile(V, array_3_prevDiscardObeyException_f, &ptp_profile, 1);
            SetDsPtpProfile(V, array_3_exceptionToCpu_f, &ptp_profile, 1);
            SetDsPtpProfile(V, array_3_discardPacket_f, &ptp_profile, 1);
            SetDsPtpProfile(V, array_10_prevDiscardObeyException_f, &ptp_profile, 1);
            SetDsPtpProfile(V, array_10_exceptionToCpu_f, &ptp_profile, 1); /*peer delay_resp_follow_up*/
            SetDsPtpProfile(V, array_10_discardPacket_f, &ptp_profile, 1);
            break;
        }
        default:
        {
            ret = CTC_E_INVALID_PARAM;
            goto out;
        }
    }

    cmd = DRV_IOW(DsPtpProfile_t, DRV_ENTRY_FLAG);
    CTC_ERROR_GOTO(DRV_IOCTL(lchip, 1, cmd, &ptp_profile), ret, out);

    p_usw_ptp_master[lchip]->device_type = device_type;

    return CTC_E_NONE;

out:
    return ret;
}

STATIC int32
_sys_usw_ptp_get_device_type(uint8 lchip, ctc_ptp_device_type_t* device_type)
{
    *device_type = p_usw_ptp_master[lchip]->device_type;

    return CTC_E_NONE;
}

STATIC int32
_sys_usw_ptp_add_device_clock(uint8 lchip, ctc_ptp_clock_t* clock)
{
    int32 ret = CTC_E_NONE;
    DsPtpProfile_m ptp_profile;
    uint8  index = 0;
    uint32 cmd = 0;
    int32 step = 0;

    sal_memset(&ptp_profile, 0, sizeof(ptp_profile));
    cmd = DRV_IOR(DsPtpProfile_t, DRV_ENTRY_FLAG);
    CTC_ERROR_GOTO(DRV_IOCTL(lchip, clock->clock_id, cmd, &ptp_profile), ret, out);

    step = DsPtpProfile_array_1_discardPacket_f - DsPtpProfile_array_0_discardPacket_f;

    for (index = 0; index < CTC_PTP_MSG_TYPE_MAX; index++)
    {
        if (CTC_FLAG_ISSET(clock->action_flag[index], CTC_PTP_ACTION_FLAG_DISCARD))
        {
            DRV_SET_FIELD_V(lchip, DsPtpProfile_t, DsPtpProfile_array_0_discardPacket_f + (index * step), &ptp_profile, 1);
        }

        if (CTC_FLAG_ISSET(clock->action_flag[index], CTC_PTP_ACTION_FLAG_COPY_TO_CPU))
        {
            DRV_SET_FIELD_V(lchip, DsPtpProfile_t, DsPtpProfile_array_0_exceptionToCpu_f + (index * step), &ptp_profile, 1);
        }

        if (CTC_FLAG_ISSET(clock->action_flag[index], CTC_PTP_ACTION_FLAG_RESIDENCE_TIME))
        {
            DRV_SET_FIELD_V(lchip, DsPtpProfile_t, DsPtpProfile_array_0_updateResidenceTime_f + (index * step), &ptp_profile, 1);
        }

        if (CTC_FLAG_ISSET(clock->action_flag[index], CTC_PTP_ACTION_FLAG_PATH_DELAY))
        {
            DRV_SET_FIELD_V(lchip, DsPtpProfile_t, DsPtpProfile_array_0_applyPathDelay_f + (index * step), &ptp_profile, 1);
        }

        if (CTC_FLAG_ISSET(clock->action_flag[index], CTC_PTP_ACTION_FLAG_IGS_ASYM_DELAY))
        {
            DRV_SET_FIELD_V(lchip, DsPtpProfile_t, DsPtpProfile_array_0_applyIngressAsymmetryDelay_f + (index * step), &ptp_profile, 1);
        }

        if (CTC_FLAG_ISSET(clock->action_flag[index], CTC_PTP_ACTION_FLAG_EGS_ASYM_DELAY))
        {
            DRV_SET_FIELD_V(lchip, DsPtpProfile_t, DsPtpProfile_array_0_applyEgressAsymmetryDelay_f + (index * step), &ptp_profile, 1);
        }
    }

    cmd = DRV_IOW(DsPtpProfile_t, DRV_ENTRY_FLAG);
    CTC_ERROR_GOTO(DRV_IOCTL(lchip, clock->clock_id, cmd, &ptp_profile), ret, out);

    return CTC_E_NONE;

out:
    return ret;
}

STATIC int32
_sys_usw_ptp_remove_device_clock(uint8 lchip, ctc_ptp_clock_t* clock)
{
    int32 ret = CTC_E_NONE;
    DsPtpProfile_m ptp_profile;
    uint32 cmd = 0;

    sal_memset(&ptp_profile, 0, sizeof(ptp_profile));
    cmd = DRV_IOW(DsPtpProfile_t, DRV_ENTRY_FLAG);
    CTC_ERROR_GOTO(DRV_IOCTL(lchip, clock->clock_id, cmd, &ptp_profile), ret, out);

    return CTC_E_NONE;

out:
    return ret;
}

STATIC int32
_sys_usw_ptp_set_adjust_delay(uint8 lchip, uint32 gport, ctc_ptp_adjust_delay_type_t type, int64 value)
{
    int32 ret = CTC_E_NONE;
    uint32 cmd = 0;
    uint8 negtive = 0;
    uint32 chan_id = 0;
    uint32 value64[2] = {0};
    sys_usw_dmps_port_info_t dmps_port_info = {0};
    DsDestChannel_m dest_channel;
    DsSrcChannel_m src_channel;

    dmps_port_info.gport = gport;
    CTC_ERROR_RETURN(sys_usw_port_api_get_dmps_property(lchip, &dmps_port_info, SYS_PORT_API_DMPS_PROP_CHAN_ID, &chan_id));
    if (!SYS_IS_NETWORK_CHANNEL(chan_id))
    {
        return CTC_E_INVALID_PARAM;
    }

    switch (type)
    {
        case CTC_PTP_ADJUST_DELAY_INGRESS_LATENCY:
        {
            sal_memset(&src_channel, 0, sizeof(src_channel));
            cmd = DRV_IOR(DsSrcChannel_t, DRV_ENTRY_FLAG);
            CTC_ERROR_GOTO(DRV_IOCTL(lchip, chan_id, cmd, &src_channel), ret, out);

            SetDsSrcChannel(V, ingressLatency_f, &src_channel, value & 0xFFFFLL);
            cmd = DRV_IOW(DsSrcChannel_t, DRV_ENTRY_FLAG);
            CTC_ERROR_GOTO(DRV_IOCTL(lchip, chan_id, cmd, &src_channel), ret, out);

            break;
        }
        case CTC_PTP_ADJUST_DELAY_EGRESS_LATENCY:
        {
            sal_memset(&dest_channel, 0, sizeof(dest_channel));
            cmd = DRV_IOR(DsDestChannel_t, DRV_ENTRY_FLAG);
            CTC_ERROR_GOTO(DRV_IOCTL(lchip, chan_id, cmd, &dest_channel), ret, out);

            SetDsDestChannel(V, egressLatency_f, &dest_channel, value & 0xFFFFLL);
            cmd = DRV_IOW(DsDestChannel_t, DRV_ENTRY_FLAG);
            CTC_ERROR_GOTO(DRV_IOCTL(lchip, chan_id, cmd, &dest_channel), ret, out);

            break;
        }
        case CTC_PTP_ADJUST_DELAY_INGRESS_ASYMMETRY:
        {
            negtive = (value >= 0) ? 0 : 1;
            if (value < 0)
            {
                value = -value;
            }

            sal_memset(&src_channel, 0, sizeof(src_channel));
            cmd = DRV_IOR(DsSrcChannel_t, DRV_ENTRY_FLAG);
            CTC_ERROR_GOTO(DRV_IOCTL(lchip, chan_id, cmd, &src_channel), ret, out);

            SetDsSrcChannel(V, asymmetryDelayNegtive_f, &src_channel, negtive);
            value64[1] = (value >> 32) & 0xFLL;
            value64[0] = value & 0xFFFFFFFFLL;
            SetDsSrcChannel(A, asymmetryDelay_f, &src_channel, value64);
            cmd = DRV_IOW(DsSrcChannel_t, DRV_ENTRY_FLAG);
            CTC_ERROR_GOTO(DRV_IOCTL(lchip, chan_id, cmd, &src_channel), ret, out);

            break;
        }
        case CTC_PTP_ADJUST_DELAY_EGRESS_ASYMMETRY:
        {
            negtive = (value >= 0) ? 0 : 1;
            if (value < 0)
            {
                value = -value;
            }

            sal_memset(&dest_channel, 0, sizeof(dest_channel));
            cmd = DRV_IOR(DsDestChannel_t, DRV_ENTRY_FLAG);
            CTC_ERROR_GOTO(DRV_IOCTL(lchip, chan_id, cmd, &dest_channel), ret, out);

            SetDsDestChannel(V, asymmetryDelayNegtive_f, &dest_channel, negtive);
            value64[1] = (value >> 32) & 0xFLL;
            value64[0] = value & 0xFFFFFFFFLL;
            SetDsDestChannel(A, asymmetryDelay_f, &dest_channel, value64);
            cmd = DRV_IOW(DsDestChannel_t, DRV_ENTRY_FLAG);
            CTC_ERROR_GOTO(DRV_IOCTL(lchip, chan_id, cmd, &dest_channel), ret, out);

            break;
        }
        case CTC_PTP_ADJUST_DELAY_PATH_DELAY:
        {
            sal_memset(&src_channel, 0, sizeof(src_channel));
            cmd = DRV_IOR(DsSrcChannel_t, DRV_ENTRY_FLAG);
            CTC_ERROR_GOTO(DRV_IOCTL(lchip, chan_id, cmd, &src_channel), ret, out);

            value64[1] = (value >> 32) & 0xFLL;
            value64[0] = value & 0xFFFFFFFFLL;
            SetDsSrcChannel(A, pathDelay_f, &src_channel, value64);
            cmd = DRV_IOW(DsSrcChannel_t, DRV_ENTRY_FLAG);
            CTC_ERROR_GOTO(DRV_IOCTL(lchip, chan_id, cmd, &src_channel), ret, out);

            break;
        }
        default:
        {
            return CTC_E_INVALID_PARAM;
        }
    }

    return CTC_E_NONE;

out:
    return ret;
}

STATIC int32
_sys_usw_ptp_get_adjust_delay(uint8 lchip, uint32 gport, ctc_ptp_adjust_delay_type_t type, int64* value)
{
    int32 ret = CTC_E_NONE;
    uint32 cmd = 0;
    uint32 chan_id = 0;
    uint8 negtive = 0;
    uint32 value64[2] = {0};
    sys_usw_dmps_port_info_t dmps_port_info = {0};
    DsDestChannel_m dest_channel;
    DsSrcChannel_m src_channel;

    dmps_port_info.gport = gport;
    CTC_ERROR_RETURN(sys_usw_port_api_get_dmps_property(lchip, &dmps_port_info, SYS_PORT_API_DMPS_PROP_CHAN_ID, &chan_id));
    if (!SYS_IS_NETWORK_CHANNEL(chan_id))
    {
        return CTC_E_INVALID_PARAM;
    }

    switch (type)
    {
        case CTC_PTP_ADJUST_DELAY_INGRESS_LATENCY:
        {
            sal_memset(&src_channel, 0, sizeof(src_channel));
            cmd = DRV_IOR(DsSrcChannel_t, DRV_ENTRY_FLAG);
            CTC_ERROR_GOTO(DRV_IOCTL(lchip, chan_id, cmd, &src_channel), ret, out);
            if (DRV_FROM_AT(lchip))
            {
                GetDsSrcChannel(A, latencyAdj1Value_f, &src_channel, value64);
            }
            else
            {
                GetDsSrcChannel(A, ingressLatency_f, &src_channel, value64);
            }
            *value = ((uint64)value64[1] & 0xF) << 32 | value64[0];

            break;
        }
        case CTC_PTP_ADJUST_DELAY_EGRESS_LATENCY:
        {
            sal_memset(&dest_channel, 0, sizeof(dest_channel));
            cmd = DRV_IOR(DsDestChannel_t, DRV_ENTRY_FLAG);
            CTC_ERROR_GOTO(DRV_IOCTL(lchip, chan_id, cmd, &dest_channel), ret ,out);

            GetDsDestChannel(A, egressLatency_f, &dest_channel, value64);
            *value = ((uint64)value64[1] & 0xF) << 32 | value64[0];

            break;
        }
        case CTC_PTP_ADJUST_DELAY_INGRESS_ASYMMETRY:
        {
            sal_memset(&src_channel, 0, sizeof(src_channel));
            cmd = DRV_IOR(DsSrcChannel_t, DRV_ENTRY_FLAG);
            CTC_ERROR_GOTO(DRV_IOCTL(lchip, chan_id, cmd, &src_channel), ret, out);
            if (DRV_FROM_AT(lchip))
            {
                negtive = GetDsSrcChannel(V, latencyAdj2Negtive_f, &src_channel);
                GetDsSrcChannel(A, latencyAdj2Value_f, &src_channel, value64);
            }
            else
            {
                negtive = GetDsSrcChannel(V, asymmetryDelayNegtive_f, &src_channel);
                GetDsSrcChannel(A, asymmetryDelay_f, &src_channel, value64);
            }
            *value = ((uint64)value64[1] & 0xF) << 32 | value64[0];
            if (negtive)
            {
                *value = - (*value);
            }

            break;
        }
        case CTC_PTP_ADJUST_DELAY_EGRESS_ASYMMETRY:
        {
            sal_memset(&dest_channel, 0, sizeof(dest_channel));
            cmd = DRV_IOR(DsDestChannel_t, DRV_ENTRY_FLAG);
            CTC_ERROR_GOTO(DRV_IOCTL(lchip, chan_id, cmd, &dest_channel), ret, out);

            negtive = GetDsDestChannel(V, asymmetryDelayNegtive_f, &dest_channel);
            GetDsDestChannel(A, asymmetryDelay_f, &dest_channel, value64);
            *value = ((uint64)value64[1] & 0xF) << 32 | value64[0];
            if (negtive)
            {
                *value = -(*value);
            }

            break;
        }
        case CTC_PTP_ADJUST_DELAY_PATH_DELAY:
        {
            sal_memset(&src_channel, 0, sizeof(src_channel));
            cmd = DRV_IOR(DsSrcChannel_t, DRV_ENTRY_FLAG);
            CTC_ERROR_GOTO(DRV_IOCTL(lchip, chan_id, cmd, &src_channel), ret, out);
            if (DRV_FROM_AT(lchip))
            {
                GetDsSrcChannel(A, latencyAdj4Value_f, &src_channel, value64);
            }
            else
            {
                GetDsSrcChannel(A, pathDelay_f, &src_channel, value64);
            }
            *value = ((uint64)value64[1] & 0xF) << 32 | value64[0];
            break;
        }
        default:
        {
            return CTC_E_INVALID_PARAM;
        }
    }

    return CTC_E_NONE;

out:
    return ret;
}

STATIC int32
_sys_usw_ptp_get_captured_ts(uint8 lchip, ctc_ptp_captured_type_t type, sys_ptp_capured_ts_t* p_cap_ts)
{
    uint32 cmd = 0;
    uint8 src_bit = 0;
    bool is_fifo_match = FALSE;
    uint8 seq_id = 0;
    uint16 adj_frc_bitmap = 0;
    TsEngineTsCaptureFifoAdjRc_m ptp_captured_adj_frc;
    sys_ptp_capured_ts_t capured_ts;

    /*check*/
    SYS_PTP_INIT_CHECK();
    CTC_PTR_VALID_CHECK(p_cap_ts);

    /*1. read ts from FIFO until the FIFO is empty*/
    if (CTC_PTP_CAPTURED_TYPE_RX == type)
    {
        SYS_PTP_RX_SOURCE_CHECK(p_cap_ts->lport_or_source);
        SYS_PTP_RX_SEQ_ID_CHECK(p_cap_ts->seq_id);

        sal_memset(&ptp_captured_adj_frc, 0, sizeof(ptp_captured_adj_frc));
        cmd = DRV_IOR(TsEngineTsCaptureFifoAdjRc_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &ptp_captured_adj_frc));

        adj_frc_bitmap = GetTsEngineTsCaptureFifoAdjRc(V, adjRcBitmap_f, &ptp_captured_adj_frc);
        seq_id = GetTsEngineTsCaptureFifoAdjRc(V, adjRcSeqId_f, &ptp_captured_adj_frc) & 0xF; /*for AT
 seq id must %16*/

        sal_memset(&capured_ts, 0, sizeof(capured_ts));
        while (adj_frc_bitmap) /*the FIFO is empty when the bitmap is 0*/
        {
            if ((p_cap_ts->seq_id == seq_id) && ((adj_frc_bitmap >> p_cap_ts->lport_or_source) & 0x1)) /*seq_id and source are all match*/
            {
                p_cap_ts->ts.seconds = GetTsEngineTsCaptureFifoAdjRc(V, adjRcSecond_f, &ptp_captured_adj_frc);
                p_cap_ts->ts.nanoseconds = GetTsEngineTsCaptureFifoAdjRc(V, adjRcNs_f, &ptp_captured_adj_frc);
                is_fifo_match   = TRUE;
            }

            /* add ts to cache*/
            for (src_bit = 0; src_bit < 9; src_bit++) /*get captured source from bitmap*/
            {
                if ((adj_frc_bitmap >> src_bit) & 0x01)
                {
                    break;
                }
            }

            capured_ts.lport_or_source = src_bit;
            capured_ts.seq_id = seq_id;
            capured_ts.ts.seconds = GetTsEngineTsCaptureFifoAdjRc(V, adjRcSecond_f, &ptp_captured_adj_frc);
            capured_ts.ts.nanoseconds = GetTsEngineTsCaptureFifoAdjRc(V, adjRcNs_f, &ptp_captured_adj_frc);
            CTC_ERROR_RETURN(_sys_usw_ptp_add_ts_cache(lchip, type, &capured_ts)); /*add ts to cache*/

            sal_memset(&ptp_captured_adj_frc, 0, sizeof(ptp_captured_adj_frc));
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &ptp_captured_adj_frc));
            adj_frc_bitmap = GetTsEngineTsCaptureFifoAdjRc(V, adjRcBitmap_f, &ptp_captured_adj_frc);
            seq_id = GetTsEngineTsCaptureFifoAdjRc(V, adjRcSeqId_f, &ptp_captured_adj_frc) & 0xF;
        }
    }
    else if (CTC_PTP_CAPTURED_TYPE_TX == type)
    {
        return CTC_E_INVALID_PARAM;
    }
    else
    {
        return CTC_E_INVALID_PARAM;
    }

    /*2. if fail to read ts from FIFO, then read ts from cache*/
    if (!is_fifo_match)
    {
        if (_sys_usw_ptp_get_ts_cache(lchip, type, p_cap_ts) != CTC_E_NONE) /*read ts from cache*/
        {
            SYS_PTP_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " [PTP] Time stamp is not ready \n");
            return CTC_E_HW_FAIL;
        }
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_usw_ptp_set_sync_intf(uint8 lchip, ctc_ptp_sync_intf_cfg_t* p_config)
{
    int32 ret = CTC_E_NONE;
    uint32 cmd = 0;
    uint32 value = 0;
    uint32 hw_mode_old = 0;
    uint32 offset_ns = 0;
    uint32 offset_s = 0;
    TsEngineOffsetAdj_m ptp_offset_adjust;
    TsEngineSyncIntfCfg_m ptp_sync_intf_cfg;
    TsEngineSyncIntfHalfPeriod_m ptp_sync_intf_half_period;
    TsEngineTsCaptureFifoAdjRc_m ptp_captured_adj_frc;
    TsEngineSyncIntfInputCode_m input_code;
    ctc_ptp_time_t time;
    sys_intr_type_t type;
    uint16 adj_frc_bitmap = 0;

    sal_memset(&type, 0, sizeof(type));
    type.intr = SYS_INTR_FUNC_PTP_SYNC_CODE_IN_RDY;
    type.sub_intr = INVG;
    CTC_ERROR_RETURN(sys_usw_interrupt_set_en(lchip, &type, p_config->hw_mode ? 0 : 1));

    /*set sync interface as input mode*/
    sal_memset(&ptp_sync_intf_cfg, 0, sizeof(ptp_sync_intf_cfg));
    SYS_EUNIT_HW_LOCK(lchip, SYS_EUNIT_M, 0);
    cmd = DRV_IOR(TsEngineSyncIntfCfg_t, DRV_ENTRY_FLAG);
    CTC_ERROR_GOTO(DRV_IOCTL(lchip, 0, cmd, &ptp_sync_intf_cfg), ret , out);
    SYS_EUNIT_HW_UNLOCK(lchip, SYS_EUNIT_M, 0);

    SetTsEngineSyncIntfCfg(V, syncIntfMode_f, &ptp_sync_intf_cfg, 0);
    if (p_config->mode == CTC_PTP_INTF_MODE_OUTPUT)
    {
        SetTsEngineSyncIntfCfg(V, syncPulseOutMask_f, &ptp_sync_intf_cfg, 1);
    }
    p_usw_ptp_master[lchip]->sync_mode[p_config->domain_id] = p_config->mode;

    SYS_EUNIT_HW_LOCK(lchip, SYS_EUNIT_M, 0);
    cmd = DRV_IOW(TsEngineSyncIntfCfg_t, DRV_ENTRY_FLAG);
    CTC_ERROR_GOTO(DRV_IOCTL(lchip, 0, cmd, &ptp_sync_intf_cfg), ret, out);
    SYS_EUNIT_HW_UNLOCK(lchip, SYS_EUNIT_M, 0);

    /*set sync interface config*/
    SetTsEngineSyncIntfCfg(V, syncIntfMode_f, &ptp_sync_intf_cfg, p_config->mode == CTC_PTP_INTF_MODE_OUTPUT ? 1 : 0);
    SetTsEngineSyncIntfCfg(V, lock_f, &ptp_sync_intf_cfg, p_config->lock ? 1 : 0);
    SetTsEngineSyncIntfCfg(V, epoch_f, &ptp_sync_intf_cfg, p_config->epoch);
    SetTsEngineSyncIntfCfg(V, accuracy_f, &ptp_sync_intf_cfg, p_config->accuracy);
    SetTsEngineSyncIntfCfg(V, syncPulseInIntrEn_f, &ptp_sync_intf_cfg,p_config->mode == CTC_PTP_INTF_MODE_1PPS_ONLY ? 1 : 0);
    SetTsEngineSyncIntfCfg(V, ignoreSyncCodeInRdy_f, &ptp_sync_intf_cfg,p_config->mode == CTC_PTP_INTF_MODE_1PPS_ONLY ? 1 : 0);
    SetTsEngineSyncIntfCfg(V, syncPulseOutPeriod_f, &ptp_sync_intf_cfg, p_config->sync_clock_hz / p_config->sync_pulse_hz);
    SetTsEngineSyncIntfCfg(V, syncPulseOutThreshold_f, &ptp_sync_intf_cfg, p_config->sync_clock_hz / p_config->sync_pulse_hz * p_config->sync_pulse_duty / 100);
    SetTsEngineSyncIntfCfg(V, syncClockOutEn_f, &ptp_sync_intf_cfg, p_config->mode == CTC_PTP_INTF_MODE_OUTPUT? 1 : 0);
    SetTsEngineSyncIntfCfg(V, syncCodeOutEnable_f, &ptp_sync_intf_cfg, p_config->mode == CTC_PTP_INTF_MODE_OUTPUT ? 1 : 0);
    SetTsEngineSyncIntfCfg(V, syncPulseOutEnable_f, &ptp_sync_intf_cfg, p_config->mode == CTC_PTP_INTF_MODE_OUTPUT ? 1 : 0);
    SetTsEngineSyncIntfCfg(V, tsCaptureEn_f, &ptp_sync_intf_cfg, p_config->mode ==CTC_PTP_INTF_MODE_OUTPUT ? 0 : 1);
    SYS_EUNIT_HW_LOCK(lchip, SYS_EUNIT_M, 0);
    cmd = DRV_IOW(TsEngineSyncIntfCfg_t, DRV_ENTRY_FLAG);
    CTC_ERROR_GOTO(DRV_IOCTL(lchip, 0, cmd, &ptp_sync_intf_cfg), ret, out);
    SYS_EUNIT_HW_UNLOCK(lchip, SYS_EUNIT_M, 0);

    /*clear code ready for mode change*/
    sal_memset(&input_code, 0, sizeof(input_code));
    cmd = DRV_IOW(TsEngineSyncIntfInputCode_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &input_code));

    /*calculate syncClock half period and syncPulse period&duty*/
    sal_memset(&ptp_sync_intf_half_period, 0, sizeof(ptp_sync_intf_half_period));
    SetTsEngineSyncIntfHalfPeriod(V, halfPeriodNs_f, &ptp_sync_intf_half_period, MCHIP_CAP(SYS_CAP_PTP_NS_OR_NNS_VALUE) / (p_config->sync_clock_hz * 2));
    SYS_EUNIT_HW_LOCK(lchip, SYS_EUNIT_M, 0);
    cmd = DRV_IOW(TsEngineSyncIntfHalfPeriod_t, DRV_ENTRY_FLAG);
    CTC_ERROR_GOTO(DRV_IOCTL(lchip, 0, cmd, &ptp_sync_intf_half_period), ret, out);
    SYS_EUNIT_HW_UNLOCK(lchip, SYS_EUNIT_M, 0);

    /*for input mode need clear first*/
    if (p_config->mode != CTC_PTP_INTF_MODE_OUTPUT)
    {
        sal_memset(&ptp_captured_adj_frc, 0, sizeof(ptp_captured_adj_frc));
        cmd = DRV_IOR(TsEngineTsCaptureFifoAdjRc_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &ptp_captured_adj_frc));

        adj_frc_bitmap = GetTsEngineTsCaptureFifoAdjRc(V, adjRcBitmap_f, &ptp_captured_adj_frc);
        while (adj_frc_bitmap) /*the FIFO is empty when the bitmap is 0*/
        {
            sal_memset(&ptp_captured_adj_frc, 0, sizeof(ptp_captured_adj_frc));
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &ptp_captured_adj_frc));
            adj_frc_bitmap = GetTsEngineTsCaptureFifoAdjRc(V, adjRcBitmap_f, &ptp_captured_adj_frc);
        }
    }
    else
    {
        SetTsEngineSyncIntfCfg(V, syncPulseOutMask_f, &ptp_sync_intf_cfg, 0);
        SYS_EUNIT_HW_LOCK(lchip, SYS_EUNIT_M, 0);
        cmd = DRV_IOW(TsEngineSyncIntfCfg_t, DRV_ENTRY_FLAG);
        CTC_ERROR_GOTO(DRV_IOCTL(lchip, 0, cmd, &ptp_sync_intf_cfg), ret, out);
        SYS_EUNIT_HW_UNLOCK(lchip, SYS_EUNIT_M, 0);

        /* read frc time*/
        sal_memset(&time, 0, sizeof(time));
        CTC_ERROR_RETURN(_sys_usw_ptp_get_frc_timestamp(lchip, &time));

        /* set toggle time*/
        if ((time.nanoseconds + MCHIP_CAP(SYS_CAP_PTP_TOD_ADJUSTING_TOGGLE_STEP)) >= MCHIP_CAP(SYS_CAP_PTP_NS_OR_NNS_VALUE))
        {
            time.seconds++;
            time.nanoseconds = time.nanoseconds + MCHIP_CAP(SYS_CAP_PTP_TOD_ADJUSTING_TOGGLE_STEP) - MCHIP_CAP(SYS_CAP_PTP_NS_OR_NNS_VALUE);
        }
        else
        {
            time.nanoseconds = time.nanoseconds + MCHIP_CAP(SYS_CAP_PTP_TOD_ADJUSTING_TOGGLE_STEP);
        }
        CTC_ERROR_RETURN(_sys_usw_ptp_set_sync_intf_toggle_time(lchip, &time));

    }

    /*sync interface config for eunit*/
    value = p_config->hw_mode << SYS_PTP_SYNC_INTF_HW_MODE_BIT | p_config->drift_time;
    if (MCHIP_EUNIT(lchip) && MCHIP_EUNIT(lchip)->mcpu_set_config)
    {
        CTC_ERROR_RETURN(MCHIP_EUNIT(lchip)->mcpu_get_config(lchip, 0, &hw_mode_old));
        CTC_ERROR_RETURN(MCHIP_EUNIT(lchip)->mcpu_set_config(lchip, 0, &value));
    }

    /*(hw_mode) input change to output need updte offset to packet module*/
    hw_mode_old = (hw_mode_old >> SYS_PTP_SYNC_INTF_HW_MODE_BIT) & 0x1;
    if(hw_mode_old && p_config->mode == CTC_PTP_INTF_MODE_OUTPUT)
    {
        SYS_EUNIT_HW_LOCK(lchip, SYS_EUNIT_M, 0);
        cmd = DRV_IOR(TsEngineOffsetAdj_t, DRV_ENTRY_FLAG);
        CTC_ERROR_GOTO(DRV_IOCTL(lchip, 0, cmd, &ptp_offset_adjust), ret, out);
        SYS_EUNIT_HW_UNLOCK(lchip, SYS_EUNIT_M, 0);
        offset_ns = GetTsEngineOffsetAdj(V, offsetNs_f, &ptp_offset_adjust);
        offset_s = GetTsEngineOffsetAdj(V, offsetSecond_f, &ptp_offset_adjust);
        CTC_ERROR_RETURN(sys_usw_packet_tx_set_property(lchip, SYS_PKT_TX_TYPE_PTP_ADJUST_OFFSET, offset_ns, offset_s));
    }

    p_usw_ptp_master[lchip]->hw_mode = p_config->hw_mode;
    CTC_ERROR_RETURN(sys_usw_packet_tx_set_property(lchip, SYS_PKT_TX_TYPE_SYNC_HW_MODE, p_config->hw_mode, 0));
    return CTC_E_NONE;

out:
    SYS_EUNIT_HW_UNLOCK(lchip, SYS_EUNIT_M, 0);
    return ret;
}

STATIC int32
_sys_usw_ptp_get_sync_intf(uint8 lchip, ctc_ptp_sync_intf_cfg_t* p_config)
{
    int32 ret = CTC_E_NONE;
    uint32 cmd = 0;
    uint32 value = 0;
    uint32 half_period_ns = 0;
    uint32 sync_pulse_out_period = 0;
    uint32 sync_pulse_out_threshold = 0;
    TsEngineSyncIntfCfg_m ptp_sync_intf_cfg;
    TsEngineSyncIntfHalfPeriod_m ptp_sync_intf_half_period;

    /*set sync interface config*/
    sal_memset(&ptp_sync_intf_cfg, 0, sizeof(ptp_sync_intf_cfg));
    SYS_EUNIT_HW_LOCK(lchip, SYS_EUNIT_M, 0);
    cmd = DRV_IOR(TsEngineSyncIntfCfg_t, DRV_ENTRY_FLAG);
    CTC_ERROR_GOTO(DRV_IOCTL(lchip, 0, cmd, &ptp_sync_intf_cfg), ret, out);

    sal_memset(&ptp_sync_intf_half_period, 0, sizeof(ptp_sync_intf_half_period));
    cmd = DRV_IOR(TsEngineSyncIntfHalfPeriod_t, DRV_ENTRY_FLAG);
    CTC_ERROR_GOTO(DRV_IOCTL(lchip, 0, cmd, &ptp_sync_intf_half_period), ret, out);
    SYS_EUNIT_HW_UNLOCK(lchip, SYS_EUNIT_M, 0);

    p_config->mode = p_usw_ptp_master[lchip]->sync_mode[p_config->domain_id];
    p_config->lock = GetTsEngineSyncIntfCfg(V, lock_f, &ptp_sync_intf_cfg);
    p_config->epoch = GetTsEngineSyncIntfCfg(V, epoch_f, &ptp_sync_intf_cfg);
    p_config->accuracy = GetTsEngineSyncIntfCfg(V, accuracy_f, &ptp_sync_intf_cfg);
    GetTsEngineSyncIntfCfg(A, syncPulseOutPeriod_f, &ptp_sync_intf_cfg, &sync_pulse_out_period);
    GetTsEngineSyncIntfCfg(A, syncPulseOutThreshold_f, &ptp_sync_intf_cfg, &sync_pulse_out_threshold);
    GetTsEngineSyncIntfHalfPeriod(A, halfPeriodNs_f, &ptp_sync_intf_half_period, &half_period_ns);

    if (0 == half_period_ns)
    {
        p_config->sync_clock_hz = 0;
    }
    else
    {
        p_config->sync_clock_hz = MCHIP_CAP(SYS_CAP_PTP_NS_OR_NNS_VALUE) / (half_period_ns * 2);
    }

    if (0 == sync_pulse_out_period)
    {
        p_config->sync_pulse_hz = 0;
        p_config->sync_pulse_duty = 0;
    }
    else
    {
        p_config->sync_pulse_hz = p_config->sync_clock_hz / sync_pulse_out_period;
        p_config->sync_pulse_duty = (sync_pulse_out_threshold * 100) / sync_pulse_out_period;
    }

    if (MCHIP_EUNIT(lchip) && MCHIP_EUNIT(lchip)->mcpu_get_config)
    {
        CTC_ERROR_RETURN(MCHIP_EUNIT(lchip)->mcpu_get_config(lchip, 0, &value));
    }
    p_config->hw_mode = (value >> SYS_PTP_SYNC_INTF_HW_MODE_BIT) & 0x1;
    p_config->drift_time = value & 0x7fffffff;

    return CTC_E_NONE;

out:
    SYS_EUNIT_HW_UNLOCK(lchip, SYS_EUNIT_M, 0);
    return ret;
}

STATIC int32
_sys_usw_ptp_set_sync_intf_toggle_time(uint8 lchip, ctc_ptp_time_t* p_toggle_time)
{
    int32 ret = CTC_E_NONE;
    uint32 cmd = 0;
    uint32  value = 0;
    TsEngineSyncIntfToggle_m ptp_sync_intf_toggle;
    TsEngineSyncIntfCfg_m ptp_sync_intf_cfg;

    /*set sync interface as input mode*/
    sal_memset(&ptp_sync_intf_cfg, 0, sizeof(ptp_sync_intf_cfg));
    cmd = DRV_IOR(TsEngineSyncIntfCfg_t, DRV_ENTRY_FLAG);
    CTC_ERROR_GOTO(DRV_IOCTL(lchip, 0, cmd, &ptp_sync_intf_cfg), ret, out);

    GetTsEngineSyncIntfCfg(A, syncIntfMode_f, &ptp_sync_intf_cfg, &value);
    SetTsEngineSyncIntfCfg(V, syncIntfMode_f, &ptp_sync_intf_cfg, 0);
    cmd = DRV_IOW(TsEngineSyncIntfCfg_t, DRV_ENTRY_FLAG);
    CTC_ERROR_GOTO(DRV_IOCTL(lchip, 0, cmd, &ptp_sync_intf_cfg), ret, out);

    /*set toggle time*/
    sal_memset(&ptp_sync_intf_toggle, 0, sizeof(ptp_sync_intf_toggle));
    SetTsEngineSyncIntfToggle(V, toggleSecond_f, &ptp_sync_intf_toggle, p_toggle_time->seconds);
    SetTsEngineSyncIntfToggle(V, toggleNs_f, &ptp_sync_intf_toggle, p_toggle_time->nanoseconds);
    SetTsEngineSyncIntfToggle(V, toggleFracNs_f, &ptp_sync_intf_toggle, p_toggle_time->nano_nanoseconds);
    cmd = DRV_IOW(TsEngineSyncIntfToggle_t, DRV_ENTRY_FLAG);
    CTC_ERROR_GOTO(DRV_IOCTL(lchip, 0, cmd, &ptp_sync_intf_toggle), ret, out);

    /*set sync interface as output mode*/
    SetTsEngineSyncIntfCfg(V, syncIntfMode_f, &ptp_sync_intf_cfg, value);
    cmd = DRV_IOW(TsEngineSyncIntfCfg_t, DRV_ENTRY_FLAG);
    CTC_ERROR_GOTO(DRV_IOCTL(lchip, 0, cmd, &ptp_sync_intf_cfg), ret, out);

    return CTC_E_NONE;

out:
    return ret;
}

STATIC int32
_sys_usw_ptp_get_sync_intf_toggle_time(uint8 lchip, ctc_ptp_time_t* p_toggle_time)
{
    int32 ret = CTC_E_NONE;
    uint32 cmd = 0;
    TsEngineSyncIntfToggle_m ptp_sync_intf_toggle;

    /*read toggle time*/
    sal_memset(&ptp_sync_intf_toggle, 0, sizeof(ptp_sync_intf_toggle));
    cmd = DRV_IOR(TsEngineSyncIntfToggle_t, DRV_ENTRY_FLAG);
    CTC_ERROR_GOTO(DRV_IOCTL(lchip, 0, cmd, &ptp_sync_intf_toggle), ret, out);

    GetTsEngineSyncIntfToggle(A, toggleSecond_f, &ptp_sync_intf_toggle, &p_toggle_time->seconds);
    GetTsEngineSyncIntfToggle(A, toggleNs_f, &ptp_sync_intf_toggle, &p_toggle_time->nanoseconds);
    GetTsEngineSyncIntfToggle(A, toggleFracNs_f, &ptp_sync_intf_toggle, &p_toggle_time->nano_nanoseconds);
    p_toggle_time->is_negative = 0;

    return CTC_E_NONE;

out:
    return ret;
}

STATIC int32
_sys_usw_ptp_get_sync_intf_code(uint8 lchip, ctc_ptp_sync_intf_code_t* g_time_code)
{
    int32 ret = CTC_E_NONE;
    uint32 cmd = 0;
    uint32 sync_code_in_rdy = 0;
    uint32 data88_to64 = 0;
    uint32 data63_to32 = 0;
    uint32 data31_to0 = 0;
    uint32 tbl_id=0;
    TsEngineSyncIntfInputCode_m input_code;
    tbl_id = (DRV_FROM_AT(lchip))? TsSyncIntfInputCode_t : TsEngineSyncIntfInputCode_t;

    sal_memset(&input_code, 0, sizeof(input_code));
    cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
    CTC_ERROR_GOTO(DRV_IOCTL(lchip, g_time_code->domain_id, cmd, &input_code), ret, out);

    GetTsEngineSyncIntfInputCode(A, syncCodeInRdy_f, &input_code, &sync_code_in_rdy);
    if (1 != sync_code_in_rdy) /*timecode has received already*/
    {
        ret = CTC_E_HW_FAIL;
        goto out;
    }

    /*get timecode*/
    GetTsEngineSyncIntfInputCode(A, data88To64_f, &input_code, &data88_to64);
    GetTsEngineSyncIntfInputCode(A, data63To32_f, &input_code, &data63_to32);
    GetTsEngineSyncIntfInputCode(A, data31To0_f, &input_code, &data31_to0);

    g_time_code->crc_error = GetTsEngineSyncIntfInputCode(V, crcErr_f, &input_code);
    g_time_code->crc = GetTsEngineSyncIntfInputCode(V, crc_f, &input_code);
    g_time_code->seconds = (data88_to64 & 0xffffff) << 24 | (data63_to32 & 0xffffff00) >> 8;
    g_time_code->nanoseconds = (data63_to32 & 0xff) << 24 | (data31_to0 & 0xffffff00) >> 8;
    g_time_code->lock = data88_to64 >> 24;
    g_time_code->accuracy = data31_to0 & 0xff;

    /*clear ready flag*/
    SetTsEngineSyncIntfInputCode(V, syncCodeInRdy_f, &input_code, 0);
    cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
    CTC_ERROR_GOTO(DRV_IOCTL(lchip, g_time_code->domain_id, cmd, &input_code), ret, out);

    return CTC_E_NONE;

out:
    return ret;
}

STATIC int32
_sys_usw_ptp_clear_sync_intf_code(uint8 lchip)
{
    int32 ret = CTC_E_NONE;
    uint32 cmd = 0;
    TsEngineSyncIntfInputCode_m input_code;

    /*clear ready flag,clear intf_code.sync_code_in_rdy*/
    sal_memset(&input_code, 0, sizeof(input_code));
    cmd = DRV_IOW(TsEngineSyncIntfInputCode_t, DRV_ENTRY_FLAG);
    CTC_ERROR_GOTO(DRV_IOCTL(lchip, 0, cmd, &input_code), ret, out);

    return CTC_E_NONE;

out:
    return ret;
}

STATIC int32
_sys_usw_ptp_set_tod_intf(uint8 lchip, ctc_ptp_tod_intf_cfg_t* config)
{
    int32 ret = CTC_E_NONE;
    uint32 cmd = 0;
    TsEngineTodCfg_m ptp_tod_cfg;
    TsEngineTsCaptureFifoAdjRc_m ptp_captured_adj_frc;
    TsEngineTsSelection_m ts_select;
    TsEngineTodPulseHwDelay_m pluse_delay;
    uint16 coreclock = 0;
    uint16 adj_frc_bitmap = 0;
    uint32 out_delay = 0;
    uint32 out_delay_nano_ns = 0;
    uint8 gran = 0;

#if 0
    /*set GPIO 12, 13 use as tod pin*/
    sys_usw_chip_set_gpio_mode(lchip, 12, CTC_CHIP_SPECIAL_MODE);
    sys_usw_chip_set_gpio_mode(lchip, 13, CTC_CHIP_SPECIAL_MODE);
#endif
    if(DRV_FROM_AT(lchip))
    {
        cmd = DRV_IOR(TsEngineTsSelection_t, DRV_ENTRY_FLAG);
        CTC_ERROR_GOTO(DRV_IOCTL(lchip, 0, cmd, &ts_select), ret, out);
        SetTsEngineTsSelection(V, todTsSel_f, &ts_select, config->domain_id? MCHIP_CAP(SYS_CAP_PTP_DOMAIN_1_RTC) : MCHIP_CAP(SYS_CAP_PTP_DOMAIN_0_RTC));/*RTC0/RTC2*/
        cmd = DRV_IOW(TsEngineTsSelection_t, DRV_ENTRY_FLAG);
        CTC_ERROR_GOTO(DRV_IOCTL(lchip, 0, cmd, &ts_select), ret, out);
    }
    /*set ToD interface config*/
    sal_memset(&ptp_tod_cfg, 0, sizeof(ptp_tod_cfg));
    cmd = DRV_IOR(TsEngineTodCfg_t, DRV_ENTRY_FLAG);
    CTC_ERROR_GOTO(DRV_IOCTL(lchip, 0, cmd, &ptp_tod_cfg), ret, out);

    gran = DRV_FROM_TMM(lchip) ? 1 : 8;
    if (config->pulse_delay < MCHIP_CAP(SYS_CAP_PTP_TOD_1PPS_DELAY))
    {
        out_delay = (MCHIP_CAP(SYS_CAP_PTP_NS_OR_NNS_VALUE) -(config->pulse_delay)) / gran;
        out_delay_nano_ns = (MCHIP_CAP(SYS_CAP_PTP_NS_OR_NNS_VALUE) -(config->pulse_delay_nns)) / gran;
        
        p_usw_ptp_master[lchip]->tod_1pps_delay = out_delay ? MCHIP_CAP(SYS_CAP_PTP_NS_OR_NNS_VALUE) - (out_delay) * gran : 0;
        p_usw_ptp_master[lchip]->tod_1pps_delay_nano_ns = out_delay_nano_ns ? MCHIP_CAP(SYS_CAP_PTP_NS_OR_NNS_VALUE) - (out_delay) * gran : 0;
    }
    else
    {
        out_delay = (config->pulse_delay - MCHIP_CAP(SYS_CAP_PTP_TOD_1PPS_DELAY)) / gran;
        out_delay_nano_ns = config->pulse_delay_nns;

        p_usw_ptp_master[lchip]->tod_1pps_delay = out_delay ? out_delay * gran + MCHIP_CAP(SYS_CAP_PTP_TOD_1PPS_DELAY) : 0;
        p_usw_ptp_master[lchip]->tod_1pps_delay_nano_ns = out_delay_nano_ns;
    }

    if (config->mode == CTC_PTP_INTF_MODE_OUTPUT)
    {
        if(DRV_FROM_AT(lchip))
        {
            SetTsEngineTodCfg(V, todPulseOutThreshold_f, &ptp_tod_cfg, (MCHIP_CAP(SYS_CAP_PTP_NS_OR_NNS_VALUE)<<2) - 4); /* unit is quanta threshold*/
            SetTsEngineTodCfg(V, todPulseReqMaskInterval_f, &ptp_tod_cfg, MCHIP_CAP(SYS_CAP_PTP_NS_OR_NNS_VALUE) - 1); /* unit is ns*/
            SetTsEngineTodCfg(V, todTsCaptureEn_f, &ptp_tod_cfg, 1); /* at need pluse out capture*/
        }
        SetTsEngineTodCfg(V, todPulseOutMask_f, &ptp_tod_cfg, 1);
        SetTsEngineTodCfg(V, todPulseOutDelay_f, &ptp_tod_cfg, config->pulse_delay == 0 ? 0 : out_delay); /* pre output 8*(125000000-todPulseOutDelay)ns */
        if (DRV_FROM_AT(lchip))
        {
            cmd = DRV_IOR(TsEngineTodPulseHwDelay_t, DRV_ENTRY_FLAG);
            CTC_ERROR_GOTO(DRV_IOCTL(lchip, 0, cmd, &pluse_delay), ret, out);
            SetTsEngineTodPulseHwDelay(V, todPulseHwDelay_f, &pluse_delay, config->pulse_delay == 0 ? 0 : out_delay << 2 | (out_delay_nano_ns*4 / MCHIP_CAP(SYS_CAP_PTP_NS_OR_NNS_VALUE)));
            cmd = DRV_IOW(TsEngineTodPulseHwDelay_t, DRV_ENTRY_FLAG);
            CTC_ERROR_GOTO(DRV_IOCTL(lchip, 0, cmd, &pluse_delay), ret, out);
        }
    }

    cmd = DRV_IOW(TsEngineTodCfg_t, DRV_ENTRY_FLAG);
    CTC_ERROR_GOTO(DRV_IOCTL(lchip, 0, cmd, &ptp_tod_cfg), ret, out);

    if (CTC_PTP_INTF_MODE_DISABLE != config->mode)
    {
        SetTsEngineTodCfg(V, todIntfMode_f, &ptp_tod_cfg, config->mode == CTC_PTP_INTF_MODE_OUTPUT ? 1 : 0);
        SetTsEngineTodCfg(V, todPulseOutEnable_f, &ptp_tod_cfg, config->mode == CTC_PTP_INTF_MODE_OUTPUT ? 1 : 0);
        SetTsEngineTodCfg(V, todTsCaptureEn_f, &ptp_tod_cfg, config->mode == CTC_PTP_INTF_MODE_OUTPUT ? 0 : 1);
        SetTsEngineTodCfg(V, todTsOutputCaptureEn_f, &ptp_tod_cfg, config->mode && config->flex_en ? 1 : 0);
        SetTsEngineTodCfg(V, todCodeOutEnable_f, &ptp_tod_cfg, config->mode == CTC_PTP_INTF_MODE_OUTPUT ? 1 : 0);
        SetTsEngineTodCfg(V, todPulseInIntrEn_f, &ptp_tod_cfg, 1);
    }
    else
    {
        SetTsEngineTodCfg(V, todIntfMode_f, &ptp_tod_cfg, 0);
        SetTsEngineTodCfg(V, todPulseOutEnable_f, &ptp_tod_cfg, 0);
        SetTsEngineTodCfg(V, todTsCaptureEn_f, &ptp_tod_cfg, 0);
        SetTsEngineTodCfg(V, todCodeOutEnable_f, &ptp_tod_cfg, 0);
        SetTsEngineTodCfg(V, todPulseInIntrEn_f, &ptp_tod_cfg, 0);
    }
    SetTsEngineTodCfg(V, todTxStopBitNum_f, &ptp_tod_cfg, config->stop_bit_num);
    SetTsEngineTodCfg(V, todEpoch_f, &ptp_tod_cfg, config->epoch);

    if(DRV_FROM_AT(lchip))
    {
        SetTsEngineTodCfg(V, todPulseOutHighPeriod_f, &ptp_tod_cfg, 10000000UL * config->pulse_duty);/*unit is ns,value is 10ms*duty*/
    }
    else
    {
        /*1ms= todPulseOutHighPeriod*512/clockCore(M)/1000*/
        CTC_ERROR_GOTO(sys_usw_get_chip_clock(lchip, &coreclock), ret, out);
        SetTsEngineTodCfg(V, todPulseOutHighPeriod_f, &ptp_tod_cfg, (coreclock * (10000 / DOWN_FRE_RATE) * config->pulse_duty) >> 9);
    }
    cmd = DRV_IOW(TsEngineTodCfg_t, DRV_ENTRY_FLAG);
    CTC_ERROR_GOTO(DRV_IOCTL(lchip, 0, cmd, &ptp_tod_cfg), ret, out);

    if(config->flex_en)
    {
        /*set flag of flex enable*/
        if (MCHIP_EUNIT(lchip) && MCHIP_EUNIT(lchip)->set_mcpu_flag)
        {
            MCHIP_EUNIT(lchip)->set_mcpu_flag( lchip, M_UNTT_FLAG_FLEX_ENABLE, M_UNTT_MISC, 1);
        }
    }
    p_usw_ptp_master[lchip]->tod_1pps_duty = config->pulse_duty;
    p_usw_ptp_master[lchip]->tod_1pps_flex_en = config->flex_en;
    p_usw_ptp_master[lchip]->tod_1pps_mode = config->mode;
    p_usw_ptp_master[lchip]->tod_1pps_thrd = config->thrd;
    /*for input mode need clear first*/
    if (config->mode == CTC_PTP_INTF_MODE_INPUT || config->mode == CTC_PTP_INTF_MODE_1PPS_ONLY)
    {
        sal_memset(&ptp_captured_adj_frc, 0, sizeof(ptp_captured_adj_frc));
        cmd = DRV_IOR(TsEngineTsCaptureFifoAdjRc_t, DRV_ENTRY_FLAG);
        CTC_ERROR_GOTO(DRV_IOCTL(lchip, 0, cmd, &ptp_captured_adj_frc), ret, out);

        adj_frc_bitmap = GetTsEngineTsCaptureFifoAdjRc(V, adjRcBitmap_f, &ptp_captured_adj_frc);
        while (adj_frc_bitmap) /*the FIFO is empty when the bitmap is 0*/
        {
            sal_memset(&ptp_captured_adj_frc, 0, sizeof(ptp_captured_adj_frc));
            CTC_ERROR_GOTO(DRV_IOCTL(lchip, 0, cmd, &ptp_captured_adj_frc), ret, out);
            adj_frc_bitmap = GetTsEngineTsCaptureFifoAdjRc(V, adjRcBitmap_f, &ptp_captured_adj_frc);
        }
    }
    else if(config->mode == CTC_PTP_INTF_MODE_OUTPUT)
    {
        SetTsEngineTodCfg(V, todPulseOutMask_f, &ptp_tod_cfg, 0);
        cmd = DRV_IOW(TsEngineTodCfg_t, DRV_ENTRY_FLAG);
        CTC_ERROR_GOTO(DRV_IOCTL(lchip, 0, cmd, &ptp_tod_cfg), ret, out);
    }

    return CTC_E_NONE;

out:
    return ret;
}

STATIC int32
_sys_usw_ptp_get_tod_intf(uint8 lchip, ctc_ptp_tod_intf_cfg_t* config)
{
    int32 ret = CTC_E_NONE;
    uint32 cmd = 0;
    TsEngineTodCfg_m ptp_tod_cfg;
    ds_t ds;

    /*get ToD interface config*/
    sal_memset(&ptp_tod_cfg, 0, sizeof(ptp_tod_cfg));
    cmd = DRV_IOR(TsEngineTodCfg_t, DRV_ENTRY_FLAG);
    CTC_ERROR_GOTO(DRV_IOCTL(lchip, 0, cmd, &ptp_tod_cfg), ret, out);

    config->mode = p_usw_ptp_master[lchip]->tod_1pps_mode;
    config->stop_bit_num = GetTsEngineTodCfg(V, todTxStopBitNum_f, &ptp_tod_cfg);
    config->epoch = GetTsEngineTodCfg(V, todEpoch_f, &ptp_tod_cfg);
    config->pulse_duty = p_usw_ptp_master[lchip]->tod_1pps_duty;
    config->pulse_delay = p_usw_ptp_master[lchip]->tod_1pps_delay;
    config->pulse_delay_nns = p_usw_ptp_master[lchip]->tod_1pps_delay_nano_ns;
    config->flex_en = p_usw_ptp_master[lchip]->tod_1pps_flex_en;
    config->thrd = p_usw_ptp_master[lchip]->tod_1pps_thrd;

    if (DRV_FROM_AT(lchip))
    {
        cmd = DRV_IOR(TsEngineTsSelection_t, DRV_ENTRY_FLAG);
        CTC_ERROR_GOTO(DRV_IOCTL(lchip, 0, cmd, &ds), ret, out);
        config->domain_id =  GetTsEngineTsSelection(V, todTsSel_f, &ds)? 1 : 0;/*RTC0/RTC2*/
    }
    return CTC_E_NONE;

out:
    return ret;
}

STATIC int32
_sys_usw_ptp_set_tod_intf_tx_code(uint8 lchip, ctc_ptp_tod_intf_code_t* tx_code)
{
    int32 ret = CTC_E_NONE;
    uint32 cmd = 0;
    TsEngineTodCodeCfg_m ptp_tod_code_cfg;

    sal_memset(&ptp_tod_code_cfg, 0, sizeof(ptp_tod_code_cfg));
    SetTsEngineTodCodeCfg(V, todClockSrc_f, &ptp_tod_code_cfg, tx_code->clock_src);
    SetTsEngineTodCodeCfg(V, todClockSrcStatus_f, &ptp_tod_code_cfg, tx_code->clock_src_status);
    SetTsEngineTodCodeCfg(V, todLeapS_f, &ptp_tod_code_cfg, tx_code->leap_second);
    SetTsEngineTodCodeCfg(V, todMonitorAlarm_f, &ptp_tod_code_cfg, tx_code->monitor_alarm);
    SetTsEngineTodCodeCfg(V, todMsgClass_f, &ptp_tod_code_cfg, tx_code->msg_class);
    SetTsEngineTodCodeCfg(V, todMsgId_f, &ptp_tod_code_cfg, tx_code->msg_id);
    SetTsEngineTodCodeCfg(V, todPayloadLen_f, &ptp_tod_code_cfg, tx_code->msg_length);
    SetTsEngineTodCodeCfg(V, todPulseStatus_f, &ptp_tod_code_cfg, tx_code->pps_status);
    SetTsEngineTodCodeCfg(V, todTacc_f, &ptp_tod_code_cfg, tx_code->pps_accuracy);

    cmd = DRV_IOW(TsEngineTodCodeCfg_t, DRV_ENTRY_FLAG);
    CTC_ERROR_GOTO(DRV_IOCTL(lchip, 0, cmd, &ptp_tod_code_cfg), ret, out);

    return CTC_E_NONE;

out:
    return ret;
}

STATIC int32
_sys_usw_ptp_get_tod_intf_tx_code(uint8 lchip, ctc_ptp_tod_intf_code_t* tx_code)
{
    int32 ret = CTC_E_NONE;
    uint32 cmd = 0;
    TsEngineTodCodeCfg_m ptp_tod_code_cfg;

    sal_memset(&ptp_tod_code_cfg, 0, sizeof(ptp_tod_code_cfg));
    cmd = DRV_IOR(TsEngineTodCodeCfg_t, DRV_ENTRY_FLAG);
    CTC_ERROR_GOTO(DRV_IOCTL(lchip, 0, cmd, &ptp_tod_code_cfg), ret, out);

    tx_code->clock_src = GetTsEngineTodCodeCfg(V, todClockSrc_f, &ptp_tod_code_cfg);
    tx_code->clock_src_status = GetTsEngineTodCodeCfg(V, todClockSrcStatus_f, &ptp_tod_code_cfg);
    tx_code->leap_second = GetTsEngineTodCodeCfg(V, todLeapS_f, &ptp_tod_code_cfg);
    tx_code->monitor_alarm = GetTsEngineTodCodeCfg(V, todMonitorAlarm_f, &ptp_tod_code_cfg);
    tx_code->msg_class = GetTsEngineTodCodeCfg(V, todMsgClass_f, &ptp_tod_code_cfg);
    tx_code->msg_id = GetTsEngineTodCodeCfg(V, todMsgId_f, &ptp_tod_code_cfg);
    tx_code->msg_length = GetTsEngineTodCodeCfg(V, todPayloadLen_f, &ptp_tod_code_cfg);
    tx_code->pps_status = GetTsEngineTodCodeCfg(V, todPulseStatus_f, &ptp_tod_code_cfg);
    tx_code->pps_accuracy = GetTsEngineTodCodeCfg(V, todTacc_f, &ptp_tod_code_cfg);

    return CTC_E_NONE;

out:
    return ret;
}

STATIC int32
_sys_usw_ptp_get_tod_intf_rx_code(uint8 lchip, ctc_ptp_tod_intf_code_t* rx_code)
{
    int32 ret = CTC_E_NONE;
    uint32 cmd = 0;
    uint32 tod_code_in_rdy = 0;
    uint8 tod_rcv_msg_byte2 = 0;
    uint8 tod_rcv_msg_byte3 = 0;
    uint8 tod_rcv_msg_byte4 = 0;
    uint8 tod_rcv_msg_byte5 = 0;
    uint8 tod_rcv_msg_byte6 = 0;
    uint8 tod_rcv_msg_byte7 = 0;
    uint8 tod_rcv_msg_byte12 = 0;
    uint8 tod_rcv_msg_byte13 = 0;
    TsEngineTodInputCode_m input_code;

    sal_memset(&input_code, 0, sizeof(input_code));
    cmd = DRV_IOR(TsEngineTodInputCode_t, DRV_ENTRY_FLAG);
    CTC_ERROR_GOTO(DRV_IOCTL(lchip, 0, cmd, &input_code), ret, out);

    GetTsEngineTodInputCode(A, todCodeInRdy_f, &input_code, &tod_code_in_rdy);
    if (1 != tod_code_in_rdy) /*message has received already*/
    {
        ret = CTC_E_HW_FAIL;
        goto out;
    }

    /*get timecode*/
    rx_code->msg_char0 = 'C';
    rx_code->msg_char1 = 'M';
    rx_code->msg_class = GetTsEngineTodInputCode(V, todRcvMsgByte0_f, &input_code);
    rx_code->msg_id = GetTsEngineTodInputCode(V, todRcvMsgByte1_f, &input_code);

    tod_rcv_msg_byte2 = GetTsEngineTodInputCode(V, todRcvMsgByte2_f, &input_code);
    tod_rcv_msg_byte3 = GetTsEngineTodInputCode(V, todRcvMsgByte3_f, &input_code);
    rx_code->msg_length = (tod_rcv_msg_byte2 << 8) + (tod_rcv_msg_byte3);

    tod_rcv_msg_byte4 = GetTsEngineTodInputCode(V, todRcvMsgByte4_f, &input_code);
    tod_rcv_msg_byte5 = GetTsEngineTodInputCode(V, todRcvMsgByte5_f, &input_code);
    tod_rcv_msg_byte6 = GetTsEngineTodInputCode(V, todRcvMsgByte6_f, &input_code);
    tod_rcv_msg_byte7 = GetTsEngineTodInputCode(V, todRcvMsgByte7_f, &input_code);
    rx_code->gps_second_time_of_week = (tod_rcv_msg_byte4 << 24) + (tod_rcv_msg_byte5 << 16) +
                                                                    (tod_rcv_msg_byte6 << 8) + (tod_rcv_msg_byte7);

    tod_rcv_msg_byte12 = GetTsEngineTodInputCode(V, todRcvMsgByte12_f, &input_code);
    tod_rcv_msg_byte13 = GetTsEngineTodInputCode(V, todRcvMsgByte13_f, &input_code);
    rx_code->gps_week = (tod_rcv_msg_byte12 << 8) + (tod_rcv_msg_byte13);

    rx_code->leap_second = GetTsEngineTodInputCode(V, todRcvMsgByte14_f, &input_code);
    rx_code->pps_status = GetTsEngineTodInputCode(V, todRcvMsgByte15_f, &input_code);
    rx_code->pps_accuracy = GetTsEngineTodInputCode(V, todRcvMsgByte16_f, &input_code);
    rx_code->crc = GetTsEngineTodInputCode(V, todRcvMsgCrc_f, &input_code);
    rx_code->crc_error = GetTsEngineTodInputCode(V, todRcvMsgCrcErr_f, &input_code);

    /*clear ready flag*/
    SetTsEngineTodInputCode(V, todCodeInRdy_f, &input_code, 0);
    cmd = DRV_IOW(TsEngineTodInputCode_t, DRV_ENTRY_FLAG);
    CTC_ERROR_GOTO(DRV_IOCTL(lchip, 0, cmd, &input_code), ret, out);

    return CTC_E_NONE;

out:
    return ret;
}

STATIC int32
_sys_usw_ptp_clear_tod_intf_code(uint8 lchip)
{
    int32 ret = CTC_E_NONE;
    uint32 cmd = 0;
    TsEngineTodInputCode_m input_code;

    /*clear ready flag,clear intf_code.tod_code_in_rdy*/
    sal_memset(&input_code, 0, sizeof(input_code));
    cmd = DRV_IOW(TsEngineTodInputCode_t, DRV_ENTRY_FLAG);
    CTC_ERROR_GOTO(DRV_IOCTL(lchip, 0, cmd, &input_code), ret, out);

    return CTC_E_NONE;

out:
    return ret;
}

#define __5_PTP_ISR__
int32
sys_tmg_ptp_isr_tx_ts_capture(uint8 lchip, uint32 intr, void* p_data)
{
    static ctc_ptp_ts_cache_t cache;
    uint8 gchip = 0;
    uint8 index = 0;
    uint8 valid_port = 0;
    uint8 mac_id = 0;
    int32 ret = CTC_E_NONE;
    uint32 cmd = 0;
    uint32 fifo_depth = 0;
    uint32 tx_cpu_fifo_data[3] = {0};
    uint64 ts_ptp = 0;
    uint32 offset_ns = 0;
    uint32 offset_s = 0;
    TsEngineOffsetAdj_m ptp_offset_adjust;
    ds_t ptp_status;
    CTC_INTERRUPT_EVENT_FUNC cb = NULL;
    SYS_PTP_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    /*check*/
    SYS_PTP_INIT_CHECK();
    PTP_CB_LOCK;
    sal_memset(&cache, 0, sizeof(cache));
    sys_usw_get_gchip_id(lchip, &gchip);

    /* get offset ts */
    sal_memset(&ptp_offset_adjust, 0, sizeof(ptp_offset_adjust));
    SYS_EUNIT_HW_LOCK(lchip, SYS_EUNIT_M, 0);
    cmd = DRV_IOR(TsEngineOffsetAdj_t, DRV_ENTRY_FLAG);
    DRV_IOCTL(lchip, 0, cmd, &ptp_offset_adjust);
    SYS_EUNIT_HW_UNLOCK(lchip, SYS_EUNIT_M, 0);
    GetTsEngineOffsetAdj(A, offsetNs_f, &ptp_offset_adjust, &offset_ns);
    GetTsEngineOffsetAdj(A, offsetSecond_f, &ptp_offset_adjust, &offset_s);

    /* read fifo depth*/
    index = intr - SYS_INTR_FUNC_DP0_MC_MAC0;//GX_TODO

    cmd = DRV_IOR(QuadSgmacTxPtpStatus_t, DRV_ENTRY_FLAG);
    CTC_ERROR_GOTO(DRV_IOCTL(lchip, index, cmd, &ptp_status),ret,out);
    fifo_depth = GetQuadSgmacTxPtpStatus(V, sgmacTxPtpFifoDepth_f, &ptp_status);
    SYS_PTP_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "intr_type:%d, tbl_index:%d, fifo_depth:%d\n", intr, index, fifo_depth);

    /*fifo depth*/
    while(fifo_depth)
    {
        /*read timestamp*/
        cmd = DRV_IOR(QuadSgmacTxPtpFifoPop_t, DRV_ENTRY_FLAG);
        CTC_ERROR_GOTO(DRV_IOCTL(lchip, index, cmd, &tx_cpu_fifo_data),ret,out);
        ts_ptp = GetQuadSgmacTxPtpFifoPop(V, currentTimestamp_f, &tx_cpu_fifo_data);
        valid_port = GetQuadSgmacTxPtpFifoPop(V, portValidBitMap_f, &tx_cpu_fifo_data);

        cache.entry[cache.entry_count].ts.seconds = (ts_ptp >> 30) & 0xffffffff;
        cache.entry[cache.entry_count].ts.nanoseconds = ts_ptp & 0x3fffffff;
        for(mac_id = 0; mac_id < MCHIP_CAP(SYS_CAP_MAX_MAC_NUM_PER_TXQM); mac_id++)
        {
            if(CTC_IS_BIT_SET(valid_port, mac_id))
            {
                cache.entry[cache.entry_count].type = CTC_PTP_CAPTURED_TYPE_TX;
                cache.entry[cache.entry_count].u.lport = sys_usw_port_api_get_lport_with_mac(lchip, mac_id + index * MCHIP_CAP(SYS_CAP_MAX_MAC_NUM_PER_TXQM));
                cache.entry[cache.entry_count].msg_type = (tx_cpu_fifo_data[2]>>(6*mac_id))&0x3;
                cache.entry[cache.entry_count].seq_id = (tx_cpu_fifo_data[2]>>(6*mac_id))&0x3C;
                if((offset_ns + cache.entry[cache.entry_count].ts.nanoseconds) < MCHIP_CAP(SYS_CAP_PTP_NS_OR_NNS_VALUE))
                {
                    cache.entry[cache.entry_count].ts.seconds += offset_s;
                    cache.entry[cache.entry_count].ts.nanoseconds += offset_ns;
                }
                else
                {
                    cache.entry[cache.entry_count].ts.seconds = cache.entry[cache.entry_count].ts.seconds + offset_s + 1;
                    cache.entry[cache.entry_count].ts.nanoseconds = cache.entry[cache.entry_count].ts.nanoseconds + offset_ns - MCHIP_CAP(SYS_CAP_PTP_NS_OR_NNS_VALUE);
                }

                SYS_PTP_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "entry:%d, type:%d, port:%d, seq_id,%d, msg_type:%d, s:%d, ns:%d, offset_s:%d , offset_ns:%d \n",
                                                        cache.entry_count,
                                                        cache.entry[cache.entry_count].type,
                                                        cache.entry[cache.entry_count].u.lport,
                                                        cache.entry[cache.entry_count].seq_id,
                                                        cache.entry[cache.entry_count].msg_type,
                                                        cache.entry[cache.entry_count].ts.seconds,
                                                        cache.entry[cache.entry_count].ts.nanoseconds,
                                                        offset_s,
                                                        offset_ns);
                cache.entry_count++;
            }
        }
        fifo_depth--;
    }
    /* call Users callback*/
    CTC_ERROR_DUMP(sys_usw_interrupt_get_event_cb(lchip, CTC_EVENT_PTP_TX_TS_CAPUTRE, &cb));
    if (cb)
    {
        (void)cb(gchip, &cache);
    }
    out:
    PTP_CB_UNLOCK;

    return ret;

}
int32
sys_usw_ptp_isr_tx_ts_capture(uint8 lchip, uint32 intr, void* p_data)
{
    static ctc_ptp_ts_cache_t cache;
    uint8 gchip = 0;
    uint8 index = 0;
    int32 ret = CTC_E_NONE;
    uint32 cmd = 0;
    uint32 fifo_depth = 0;
    uint32 tx_cpu_fifo_data[3] = {0};
    uint64 ts_ptp = 0;
    uint32 offset_ns = 0;
    uint32 offset_s = 0;
    McHataTxCpuFifoPop_m ptp_tx_cpu_fifo_pop;
    TsEngineOffsetAdj_m ptp_offset_adjust;
    CTC_INTERRUPT_EVENT_FUNC cb = NULL;

    SYS_PTP_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    /*check*/
    SYS_PTP_INIT_CHECK();
    PTP_CB_LOCK;
    sal_memset(&cache, 0, sizeof(cache));
    if (MCHIP_PTP(lchip)->isr_tx_ts_capture)
    {
        ret = MCHIP_PTP(lchip)->isr_tx_ts_capture(lchip, intr, (void*)&cache);
        goto out;
    }

    sys_usw_get_gchip_id(lchip, &gchip);

    /* get offset ts */
    sal_memset(&ptp_offset_adjust, 0, sizeof(ptp_offset_adjust));
    SYS_EUNIT_HW_LOCK(lchip, SYS_EUNIT_M, 0);
    cmd = DRV_IOR(TsEngineOffsetAdj_t, DRV_ENTRY_FLAG);
    DRV_IOCTL(lchip, 0, cmd, &ptp_offset_adjust);
    SYS_EUNIT_HW_UNLOCK(lchip, SYS_EUNIT_M, 0);
    GetTsEngineOffsetAdj(A, offsetNs_f, &ptp_offset_adjust, &offset_ns);
    GetTsEngineOffsetAdj(A, offsetSecond_f, &ptp_offset_adjust, &offset_s);

    /* read ts from fifo*/
    index = intr - SYS_INTR_FUNC_DP0_MC_MAC0;
    cmd = DRV_IOR(McHataTxDebugStats_t, McHataTxDebugStats_dbgHataTxTsToCpuFifoDepth_f);
    CTC_ERROR_GOTO(DRV_FIELD_IOCTL(lchip, index, cmd, &fifo_depth),ret,out);

    SYS_PTP_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "intr_type:%d, tbl_index:%d, fifo_depth:%d\n", intr, index, fifo_depth);

    /*fifo depth*/
    while(fifo_depth)
    {
        cmd = DRV_IOR(McHataTxCpuFifoPop_t, DRV_ENTRY_FLAG);
        sal_memset(&ptp_tx_cpu_fifo_pop, 0, sizeof(ptp_tx_cpu_fifo_pop));
        CTC_ERROR_GOTO(DRV_IOCTL(lchip, index, cmd, &ptp_tx_cpu_fifo_pop),ret,out);
        /*ptpPortId[5:0],ptpTimeStamp[61:0](s[61:30],ns[29:0]), ptpSequenceId[3:0], ptpMsgType[1:0]*/
        GetMcHataTxCpuFifoPop(A, hataTxCpuFifoPopRdData_f, &ptp_tx_cpu_fifo_pop, tx_cpu_fifo_data);

        SYS_PTP_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "tx_cpu_fifo_data[0]:0x%x, tx_cpu_fifo_data[1]:0x%x, tx_cpu_fifo_data[2]:0x%x\n",
                                               tx_cpu_fifo_data[0],tx_cpu_fifo_data[1],tx_cpu_fifo_data[2]);

        cache.entry[cache.entry_count].type = CTC_PTP_CAPTURED_TYPE_TX;
        cache.entry[cache.entry_count].u.lport = sys_usw_port_api_get_lport_with_mac(lchip, (tx_cpu_fifo_data[2] >> 4) + index * MCHIP_CAP(SYS_CAP_MAX_MAC_NUM_PER_TXQM));
        cache.entry[cache.entry_count].seq_id = (tx_cpu_fifo_data[0] >> 2) & 0xF;
        cache.entry[cache.entry_count].msg_type = tx_cpu_fifo_data[0] & 0x3; /*mac msg_type map to ptp msg_type*/
        ts_ptp = ((uint64)tx_cpu_fifo_data[2] & 0xF) << 58 | (uint64)tx_cpu_fifo_data[1] << 26 | tx_cpu_fifo_data[0] >> 6;
        cache.entry[cache.entry_count].ts.seconds = (ts_ptp >> 30) & 0xffffffff;
        cache.entry[cache.entry_count].ts.nanoseconds = ts_ptp & 0x3fffffff;

        if((offset_ns + cache.entry[cache.entry_count].ts.nanoseconds) < MCHIP_CAP(SYS_CAP_PTP_NS_OR_NNS_VALUE))
        {
            cache.entry[cache.entry_count].ts.seconds += offset_s;
            cache.entry[cache.entry_count].ts.nanoseconds += offset_ns;
        }
        else
        {
            cache.entry[cache.entry_count].ts.seconds = cache.entry[cache.entry_count].ts.seconds + offset_s + 1;
            cache.entry[cache.entry_count].ts.nanoseconds = cache.entry[cache.entry_count].ts.nanoseconds + offset_ns - MCHIP_CAP(SYS_CAP_PTP_NS_OR_NNS_VALUE);
        }

        SYS_PTP_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "entry:%d, type:%d, port:%d, seq_id,%d, msg_type:%d, s:%d, ns:%d, offset_s:%d , offset_ns:%d \n",
                                                cache.entry_count,
                                                cache.entry[cache.entry_count].type,
                                                cache.entry[cache.entry_count].u.lport,
                                                cache.entry[cache.entry_count].seq_id,
                                                cache.entry[cache.entry_count].msg_type,
                                                cache.entry[cache.entry_count].ts.seconds,
                                                cache.entry[cache.entry_count].ts.nanoseconds,
                                                offset_s,
                                                offset_ns);
        cache.entry_count++;
        fifo_depth--;
    }

    /* call Users callback*/
    CTC_ERROR_DUMP(sys_usw_interrupt_get_event_cb(lchip, CTC_EVENT_PTP_TX_TS_CAPUTRE, &cb));
    if (cb)
    {
        (void)cb(gchip, &cache);
    }
    out:
    PTP_CB_UNLOCK;

    return ret;
}

int32
sys_usw_ptp_isr_flexe_tx_ts_capture(uint8 lchip, uint32 intr, void* p_data)
{
    static ctc_ptp_ts_cache_t cache;
    uint8 gchip = 0;
    uint8 index = 0;
    int32 ret = CTC_E_NONE;
    uint32 cmd = 0;
    uint32 fifo_depth = 0;
    uint32 txCaptureInfo = 0;
    uint32 txCaptureInstId = 0;
    uint64 ts_ptp = 0;
    sys_usw_dmps_port_info_t dmps_port_info = {0};
    sys_dmps_flexe_phy_inst_t phy_inst;
    FlexeMgrTxCaptureData_m flexe_tx_capture_data;
    CTC_INTERRUPT_EVENT_FUNC cb = NULL;

    SYS_PTP_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    /*check*/
    SYS_PTP_INIT_CHECK();

    sys_usw_get_gchip_id(lchip, &gchip);

    /* read ts from fifo*/
    sal_memset(&cache, 0, sizeof(cache));
    cache.entry_count = 0;

    index = intr - SYS_INTR_FUNC_FLEX_DP0;
    cmd = DRV_IOR(FlexeMgrFifoDepth_t, FlexeMgrFifoDepth_flexeMgrTsCaptureFifoFifoDepth_f);
    CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, index, cmd, &fifo_depth));

    SYS_PTP_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "intr_type:%d, tbl_index:%d, fifo_depth:%d\n", intr, index, fifo_depth);

    /*fifo depth*/
    while(fifo_depth)
    {
        cmd = DRV_IOR(FlexeMgrTxCaptureData_t, DRV_ENTRY_FLAG);
        sal_memset(&flexe_tx_capture_data, 0, sizeof(flexe_tx_capture_data));
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &flexe_tx_capture_data));
        /*txCaptureInfo:*/
        txCaptureInfo = GetFlexeMgrTxCaptureData(V, txCaptureInfo_f, &flexe_tx_capture_data);
        txCaptureInstId = GetFlexeMgrTxCaptureData(V, txCaptureInstId_f, &flexe_tx_capture_data);
        GetFlexeMgrTxCaptureData(A, txCaptureTsSNs_f, &flexe_tx_capture_data, &ts_ptp);

        phy_inst.asic_inst_id[0] = txCaptureInstId & 0x7;
        phy_inst.dp_id = index;
        dmps_port_info.gport = 0;
        ret = sys_usw_port_api_get_dmps_property(lchip, &dmps_port_info, SYS_PORT_API_DMPS_PROP_GET_PHY_INST_ID, (void*)&phy_inst);
        if(ret == CTC_E_NONE)
        {
            cache.entry[cache.entry_count].type = CTC_PTP_CAPTURED_TYPE_TX_FLEXE;
            cache.entry[cache.entry_count].u.serdes_id = phy_inst.serdes_id;
            cache.entry[cache.entry_count].seq_id = (txCaptureInfo >> 2) & 0xF;
            cache.entry[cache.entry_count].msg_type = txCaptureInfo & 0x3;
            cache.entry[cache.entry_count].ts.seconds = (ts_ptp >> 30) & 0xffffffff;
            cache.entry[cache.entry_count].ts.nanoseconds = ts_ptp & 0x3fffffff;

            SYS_PTP_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "entry:%d, type:%d, txCaptureInstId:%d, seq_id,%d, msg_type:%d, s:%d, ns:%d\n",
                                                    cache.entry_count,
                                                    cache.entry[cache.entry_count].type,
                                                    cache.entry[cache.entry_count].u.lport,
                                                    cache.entry[cache.entry_count].seq_id,
                                                    cache.entry[cache.entry_count].msg_type,
                                                    cache.entry[cache.entry_count].ts.seconds,
                                                    cache.entry[cache.entry_count].ts.nanoseconds);
            cache.entry_count++;
        }
        fifo_depth--;
    }

    if(cache.entry_count)
    {
        /* call Users callback*/
        CTC_ERROR_DUMP(sys_usw_interrupt_get_event_cb(lchip, CTC_EVENT_PTP_TX_TS_CAPUTRE, &cb));
        if (cb)
        {
            (void)cb(gchip, &cache);
        }
    }

    return ret;
}

int32
sys_usw_ptp_isr_tod_tx_ts_capture(uint8 lchip, uint32 intr, void* p_data)
{
    uint8 gchip = 0;
    uint32 cmd = 0;
    TsEngineTodInputTs_m ptp_captured_ts;
    TsEngineTodCfg_m ptp_tod_cfg;
    ctc_ptp_rx_ts_message_t tod_message;
    CTC_INTERRUPT_EVENT_FUNC cb = NULL;
    uint8 send_buf[SYS_PTP_TOD_MESSAGE_LENTH]={0};

    if(!p_usw_ptp_master[lchip]->tod_1pps_flex_en && !DRV_FROM_AT(lchip))
    {
        return CTC_E_NONE;
    }
    sal_memset(&ptp_captured_ts, 0, sizeof(ptp_captured_ts));
    sal_memset(&tod_message, 0, sizeof(ctc_ptp_rx_ts_message_t));
    sal_memset(&ptp_tod_cfg, 0, sizeof(ptp_tod_cfg));

    sys_usw_get_gchip_id(lchip, &gchip);

    if(p_usw_ptp_master[lchip]->tod_1pps_mode == 1 || (DRV_FROM_AT(lchip)&&p_usw_ptp_master[lchip]->tod_1pps_mode==CTC_PTP_INTF_MODE_OUTPUT))/*output*/
    {
        cmd = DRV_IOR(TsEngineTsCaptureFifoAdjRc_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &ptp_captured_ts));

        tod_message.source = CTC_PTP_TIEM_INTF_TOD_1PPS;
        tod_message.captured_ts.seconds = GetTsEngineTsCaptureFifoAdjRc(V, adjRcSecond_f, &ptp_captured_ts);
        tod_message.captured_ts.nanoseconds = GetTsEngineTsCaptureFifoAdjRc(V, adjRcNs_f, &ptp_captured_ts);
        tod_message.u.flex.length = SYS_PTP_TOD_MESSAGE_LENTH;
        tod_message.u.flex.data = send_buf;

        /*call Users callback to return captured ts and get encode message*/
        CTC_ERROR_RETURN(sys_usw_interrupt_get_event_cb(lchip, CTC_EVENT_PTP_INPUT_CODE_READY, &cb));
        if (cb)
        {
            (void)cb(gchip, &tod_message);
        }
        if(!DRV_FROM_AT(lchip))
        {
            /*write ToD code to share memory*/
            if (MCHIP_EUNIT(lchip) && MCHIP_EUNIT(lchip)->mcpu_write_data)
            {
                MCHIP_EUNIT(lchip)->mcpu_write_data(lchip, M_UNTT_MISC, (uint32*)tod_message.u.flex.data, SYS_PTP_TOD_MESSAGE_LENTH / 4);
            }

            /*set flag of ready to send*/
            if (MCHIP_EUNIT(lchip) && MCHIP_EUNIT(lchip)->set_mcpu_flag)
            {
                MCHIP_EUNIT(lchip)->set_mcpu_flag( lchip, M_UNTT_FLAG_CODE_READY, M_UNTT_MISC, 1);
            }
        }
        else
        {
            /*write ToD code to share memory*/
            if (MCHIP_EUNIT(lchip) && MCHIP_EUNIT(lchip)->set_cfg)
            {
                /*flex mode use user code format from cb*/
                if(!p_usw_ptp_master[lchip]->tod_1pps_flex_en)
                {
                    uint32 weeks = 0;
                    /*change time format from gps to TAI*/
                    if(tod_message.captured_ts.seconds < MCHIP_CAP(SYS_CAP_PTP_TAI_TO_GPS_SECONDS))
                    {
                        tod_message.captured_ts.seconds = MCHIP_CAP(SYS_CAP_PTP_TAI_TO_GPS_SECONDS);
                    }

                    tod_message.captured_ts.seconds = tod_message.captured_ts.seconds - MCHIP_CAP(SYS_CAP_PTP_TAI_TO_GPS_SECONDS);
                    weeks = tod_message.captured_ts.seconds / MCHIP_CAP(SYS_CAP_PTP_SECONDS_OF_EACH_WEEK);
                    tod_message.captured_ts.seconds -= weeks * MCHIP_CAP(SYS_CAP_PTP_SECONDS_OF_EACH_WEEK);
                    /*bulid message by protocol*/
                    tod_message.u.flex.data[0] = 'C';
                    tod_message.u.flex.data[1] = 'M';
                    tod_message.u.flex.data[2] = 0x01;
                    tod_message.u.flex.data[3] = 0x20;
                    tod_message.u.flex.data[4] = 0x00;  /*data[4][5] for msg_length*/
                    tod_message.u.flex.data[5] = 0x10;
                    tod_message.u.flex.data[6] = tod_message.captured_ts.seconds>>24;  /*data[6][7][8][9] for gps_second_time_of_week*/
                    tod_message.u.flex.data[7] = (tod_message.captured_ts.seconds>>16)&0xff;
                    tod_message.u.flex.data[8] = (tod_message.captured_ts.seconds>>8)&0xff;
                    tod_message.u.flex.data[9] = tod_message.captured_ts.seconds&0xff;
                    /*data[10][11][12][13] reserved*/
                    tod_message.u.flex.data[14] = (weeks>>8)&0xff;  /*data[14][15] for gps_weeks*/
                    tod_message.u.flex.data[15] = weeks&0xff;
                    tod_message.u.flex.data[16] = 0x00;  /*data[16] for leap_second*/
                    tod_message.u.flex.data[17] = 0x00;  /*data[17] for pps_status*/
                    tod_message.u.flex.data[18] = 0x00;  /*data[17] for pps_accuracy*/
                    /*data[19][20][21] reserved*/
                    tod_message.u.flex.data[22] = _sys_usw_ptp_caculate_tod_crc(&tod_message.u.flex.data[2], 20);
                }
                MCHIP_EUNIT(lchip)->set_cfg(lchip, SYS_EUNIT_CFG_TOD, (uint32*)tod_message.u.flex.data);
            }
        }

    }

    return CTC_E_NONE;
}

/**
 @brief  PTP RX Ts capture isr
*/
int32
sys_usw_ptp_isr_rx_ts_capture(uint8 lchip, uint32 intr, void* p_data)
{
    uint8 gchip = 0;
    uint32 cmd = 0;
    uint8 src_bit = 0;
    uint16 adj_frc_bitmap = 0;
    TsEngineTsCaptureFifoAdjRc_m ptp_captured_adj_frc;
    ctc_ptp_time_t captured_ts;
    sys_ptp_capured_ts_t sys_capured_ts;
    ctc_ptp_rx_ts_message_t rx_message;
    CTC_INTERRUPT_EVENT_FUNC cb = NULL;

    /*check*/
    SYS_PTP_INIT_CHECK();

    CTC_ERROR_RETURN(sys_usw_get_gchip_id(lchip, &gchip));

    sal_memset(&ptp_captured_adj_frc, 0, sizeof(ptp_captured_adj_frc));
    cmd = DRV_IOR(TsEngineTsCaptureFifoAdjRc_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &ptp_captured_adj_frc));

    sal_memset(&captured_ts, 0, sizeof(captured_ts));
    sal_memset(&sys_capured_ts, 0, sizeof(sys_capured_ts));
    sal_memset(&rx_message, 0, sizeof(rx_message));
    adj_frc_bitmap = GetTsEngineTsCaptureFifoAdjRc(V, adjRcBitmap_f, &ptp_captured_adj_frc);
    while (adj_frc_bitmap) /*the FIFO is empty when the bitmap is 0*/
    {
        for (src_bit = 0; src_bit < 9; src_bit++) /*get captured source from bitmap*/
        {
            if ((adj_frc_bitmap >> src_bit) & 0x01)
            {
                break;
            }
        }

        if ((!DRV_FROM_AT(lchip)&&(src_bit != SYS_PTP_TIEM_INTF_SYNC_PULSE) && (src_bit != SYS_PTP_TIEM_INTF_TOD_1PPS))
            ||(DRV_FROM_AT(lchip)&&(src_bit != SYS_AT_PTP_TIEM_INTF_SYNC_PULSE_0) && (src_bit != SYS_AT_PTP_TIEM_INTF_TOD_1PPS)
            && (src_bit != SYS_AT_PTP_TIEM_INTF_SYNC_PULSE_1)))
        {
            CTC_ERROR_RETURN(_sys_usw_ptp_map_captured_src(lchip, &(rx_message.source), &src_bit, 0));
            rx_message.captured_ts.seconds = GetTsEngineTsCaptureFifoAdjRc(V, adjRcSecond_f, &ptp_captured_adj_frc);
            rx_message.captured_ts.nanoseconds = GetTsEngineTsCaptureFifoAdjRc(V, adjRcNs_f, &ptp_captured_adj_frc);

            /* call Users callback*/
            CTC_ERROR_RETURN(sys_usw_interrupt_get_event_cb(lchip, CTC_EVENT_PTP_INPUT_CODE_READY, &cb));
            if (cb)
            {
                (void)cb(gchip, &rx_message);
            }
        }
        else  /* not mactch source, add ts to cache*/
        {
            sys_capured_ts.lport_or_source = src_bit;
            sys_capured_ts.seq_id = 0;
            sys_capured_ts.ts.seconds = GetTsEngineTsCaptureFifoAdjRc(V, adjRcSecond_f, &ptp_captured_adj_frc);
            sys_capured_ts.ts.nanoseconds = GetTsEngineTsCaptureFifoAdjRc(V, adjRcNs_f, &ptp_captured_adj_frc);
            CTC_ERROR_RETURN(_sys_usw_ptp_add_ts_cache(lchip, CTC_PTP_CAPTURED_TYPE_RX, &sys_capured_ts)); /*add ts to cache*/
        }

        sal_memset(&ptp_captured_adj_frc, 0, sizeof(ptp_captured_adj_frc));
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &ptp_captured_adj_frc));
        adj_frc_bitmap = GetTsEngineTsCaptureFifoAdjRc(V, adjRcBitmap_f, &ptp_captured_adj_frc);
    }

    return CTC_E_NONE;
}

/**
 @brief  PTP TOD 1PPS in isr
*/
int32
sys_usw_ptp_isr_tod_pulse_in(uint8 lchip, uint32 intr, void* p_data)
{
    uint32 cmd = 0;
    ctc_ptp_time_t captured_ts;
    ctc_ptp_time_t offset_ts;
    ctc_ptp_rx_ts_message_t tod_message;
    CTC_INTERRUPT_EVENT_FUNC cb = NULL;
    TsEngineTsCaptureFifoAdjRc_m ptp_captured_ts;
    uint8 gchip = 0;

    if(CTC_PTP_INTF_MODE_1PPS_ONLY != p_usw_ptp_master[lchip]->tod_1pps_mode)
    {
        return CTC_E_NONE;
    }
    
    sal_memset(&tod_message, 0, sizeof(tod_message));
    sal_memset(&captured_ts, 0, sizeof(ctc_ptp_time_t));
    sal_memset(&offset_ts, 0, sizeof(ctc_ptp_time_t));

    /* 1. read captured ts from fifo*/
    cmd = DRV_IOR(TsEngineTsCaptureFifoAdjRc_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &ptp_captured_ts));
    tod_message.captured_ts.seconds = GetTsEngineTsCaptureFifoAdjRc(V, adjRcSecond_f, &ptp_captured_ts);
    tod_message.captured_ts.nanoseconds = GetTsEngineTsCaptureFifoAdjRc(V, adjRcNs_f, &ptp_captured_ts);
    captured_ts.seconds = tod_message.captured_ts.seconds;
    captured_ts.nanoseconds = tod_message.captured_ts.nanoseconds;

    SYS_PTP_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "Adjusted before captured_ts senocds %d nanoseconds %d 1pps_delay %d\n", captured_ts.seconds,  captured_ts.nanoseconds, p_usw_ptp_master[lchip]->tod_1pps_delay);

    sys_usw_get_gchip_id(lchip, &gchip);

    /* 2. call Users callback to return captured ts */
    CTC_ERROR_RETURN(sys_usw_interrupt_get_event_cb(lchip, CTC_EVENT_PTP_INPUT_CODE_READY, &cb));
    if (cb)
    {
        (void)cb(gchip, &tod_message);
    }

    /* 3. if thrd == 0xffffffff not adjust ts */
    if (p_usw_ptp_master[lchip]->tod_1pps_thrd == CTC_MAX_UINT32_VALUE)
    {
        return CTC_E_NONE;
    }
    
    /* 4. adjust captured ts*/
    if (p_usw_ptp_master[lchip]->tod_1pps_delay >= MCHIP_CAP(SYS_CAP_PTP_TOD_1PPS_DELAY))  /* tod_1pps_delay value bit 31 means delay < 0 */
    {
        if ((p_usw_ptp_master[lchip]->tod_1pps_delay - MCHIP_CAP(SYS_CAP_PTP_TOD_1PPS_DELAY) + captured_ts.nanoseconds) > MCHIP_CAP(SYS_CAP_PTP_NS_OR_NNS_VALUE))/*1pps delay between master and slave*/
        {
            captured_ts.seconds = captured_ts.seconds + 1;
            captured_ts.nanoseconds = p_usw_ptp_master[lchip]->tod_1pps_delay - MCHIP_CAP(SYS_CAP_PTP_TOD_1PPS_DELAY) + captured_ts.nanoseconds - MCHIP_CAP(SYS_CAP_PTP_NS_OR_NNS_VALUE);
        }
        else
        {
            captured_ts.nanoseconds = p_usw_ptp_master[lchip]->tod_1pps_delay - MCHIP_CAP(SYS_CAP_PTP_TOD_1PPS_DELAY) + captured_ts.nanoseconds;
        }
        captured_ts.nano_nanoseconds = p_usw_ptp_master[lchip]->tod_1pps_delay_nano_ns;
    }
    else
    {
        if (p_usw_ptp_master[lchip]->tod_1pps_delay > captured_ts.nanoseconds) /*1pps delay between master and slave*/
        {
            captured_ts.seconds = captured_ts.seconds ? (captured_ts.seconds - 1) : 0;
            captured_ts.nanoseconds = MCHIP_CAP(SYS_CAP_PTP_NS_OR_NNS_VALUE) + captured_ts.nanoseconds - p_usw_ptp_master[lchip]->tod_1pps_delay;
            captured_ts.nano_nanoseconds = p_usw_ptp_master[lchip]->tod_1pps_delay_nano_ns;
        }
        else
        {
            captured_ts.nanoseconds = captured_ts.nanoseconds - p_usw_ptp_master[lchip]->tod_1pps_delay;
            captured_ts.nano_nanoseconds = p_usw_ptp_master[lchip]->tod_1pps_delay_nano_ns?(MCHIP_CAP(SYS_CAP_PTP_NS_OR_NNS_VALUE) - p_usw_ptp_master[lchip]->tod_1pps_delay_nano_ns):0;
            captured_ts.nanoseconds = p_usw_ptp_master[lchip]->tod_1pps_delay_nano_ns? (captured_ts.nanoseconds-1):captured_ts.nanoseconds;
        }
    }
    SYS_USW_REGISTER_WB_SYNC_EN(lchip, CTC_FEATURE_PTP, SYS_WB_APPID_PTP_SUBID_MASTER, 1);
    p_usw_ptp_master[lchip]->tod_1pps_delay = 0;
    SYS_PTP_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "Adjusted after captured_ts senocds %d nanoseconds %d\n", captured_ts.seconds,  captured_ts.nanoseconds);

    /* 5. calculate offset*/
    if (captured_ts.nanoseconds > p_usw_ptp_master[lchip]->tod_1pps_thrd)
    {
        offset_ts.nanoseconds = MCHIP_CAP(SYS_CAP_PTP_NS_OR_NNS_VALUE) - captured_ts.nanoseconds;
    }
    else
    {
        offset_ts.nanoseconds = captured_ts.nanoseconds;
        offset_ts.is_negative = 1;
    }
    SYS_PTP_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "Adjusted offset senocds %d nanoseconds %d is_negative %d\n", offset_ts.seconds, offset_ts.nanoseconds, offset_ts.is_negative);

    /* 6. adjust offset */
    CTC_ERROR_RETURN(sys_usw_ptp_adjust_clock_offset(lchip, &offset_ts));
    return CTC_E_NONE;
}

/**
 @brief  PTP TOD code ready isr
*/
int32
sys_usw_ptp_tod_code_rdy(uint8 lchip, uint8 flex_en, void* p_input_code)
{
    uint8 gchip = 0;
    uint32 cmd = 0;
    uint8 tod_rcv_msg_byte0 = 0;
    uint8 tod_rcv_msg_byte1 = 0;
    uint8 tod_rcv_msg_byte2 = 0;
    uint8 tod_rcv_msg_byte3 = 0;
    uint8 tod_rcv_msg_byte4 = 0;
    uint8 tod_rcv_msg_byte5 = 0;
    uint8 tod_rcv_msg_byte6 = 0;
    uint8 tod_rcv_msg_byte7 = 0;
    uint8 tod_rcv_msg_byte12 = 0;
    uint8 tod_rcv_msg_byte13 = 0;
    uint8 tod_rcv_msg_byte14 = 0;
    uint8 tod_rcv_msg_byte15 = 0;
    uint8 tod_rcv_msg_byte16 = 0;
    uint8 tod_rcv_msg_crc = 0;
    uint8 tod_rcv_msg_crc_error = 0;
    ctc_ptp_rx_ts_message_t tod_message;
    CTC_INTERRUPT_EVENT_FUNC cb = NULL;
    TsEngineTodInputCode_m input_code;
    TsEngineTodInputTs_m ptp_captured_ts;
    sal_memset(&ptp_captured_ts, 0, sizeof(ptp_captured_ts));
    sal_memset(&input_code, 0,sizeof(input_code));

    //SYS_PTP_INIT_CHECK();
    sys_usw_get_gchip_id(lchip, &gchip);

    if(CTC_PTP_INTF_MODE_1PPS_ONLY == p_usw_ptp_master[lchip]->tod_1pps_mode)
    {
        goto OUT;
    }
    if(flex_en)
    {
        uint8 rcv_buf[SYS_PTP_TOD_MESSAGE_LENTH]={0};
        if(!DRV_FROM_AT(lchip))
        {
            /*read ToD code from share memory*/
            if (MCHIP_EUNIT(lchip) && MCHIP_EUNIT(lchip)->mcpu_read_data)
            {
                MCHIP_EUNIT(lchip)->mcpu_read_data(lchip, M_UNTT_MISC, (uint32*)rcv_buf, SYS_PTP_TOD_MESSAGE_LENTH / 4);
            }

            /*clean flag of ToD code ready*/
            if (MCHIP_EUNIT(lchip) && MCHIP_EUNIT(lchip)->set_mcpu_flag)
            {
                MCHIP_EUNIT(lchip)->set_mcpu_flag( lchip, M_UNTT_FLAG_CODE_READY, M_UNTT_MISC, 0);
            }
        }
        else
        {
            sal_memcpy(&input_code, p_input_code, sizeof(SYS_PTP_TOD_MESSAGE_LENTH));
        }

        sal_memset(&tod_message, 0, sizeof(tod_message));
        tod_message.source = CTC_PTP_TIEM_INTF_TOD_1PPS;
        tod_message.u.flex.length = SYS_PTP_TOD_MESSAGE_LENTH;
        tod_message.u.flex.data = rcv_buf;

        cmd = DRV_IOR(TsEngineTodInputTs_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &ptp_captured_ts));
        tod_message.captured_ts.seconds = GetTsEngineTodInputTs(V, captureAdjRcSecond_f, &ptp_captured_ts);
        tod_message.captured_ts.nanoseconds = GetTsEngineTodInputTs(V, captureAdjRcNs_f, &ptp_captured_ts);

        /*call Users callback to return code message */
        CTC_ERROR_RETURN(sys_usw_interrupt_get_event_cb(lchip, CTC_EVENT_PTP_INPUT_CODE_READY, &cb));
        if (cb)
        {
            (void)cb(gchip, &tod_message);
        }

        return CTC_E_NONE;
    }
    else
    {
        int32 ret = CTC_E_NONE;
        ctc_ptp_time_t offset;
        ctc_ptp_time_t input_ts;
        ctc_ptp_time_t captured_ts;
        sal_memset(&captured_ts, 0, sizeof(ctc_ptp_time_t));

        if(!DRV_FROM_AT(lchip))
        {
            sal_memcpy(&input_code, p_input_code, sizeof(input_code));
        }
        else/*from at must mask 2 Byte Header*/
        {
            sal_memcpy(&input_code, (uint8*)p_input_code+2, sizeof(input_code));
        }

        /*get timecode*/
        if(DRV_FROM_AT(lchip))
        {
            tod_rcv_msg_byte0 = *((uint8*)p_input_code+2);
            tod_rcv_msg_byte1 = *((uint8*)p_input_code+3);
            tod_rcv_msg_byte2 = *((uint8*)p_input_code+4);
            tod_rcv_msg_byte3 = *((uint8*)p_input_code+5);
            tod_rcv_msg_byte4 = *((uint8*)p_input_code+6);
            tod_rcv_msg_byte5 = *((uint8*)p_input_code+7);
            tod_rcv_msg_byte6 = *((uint8*)p_input_code+8);
            tod_rcv_msg_byte7 = *((uint8*)p_input_code+9);
            tod_rcv_msg_byte12 = *((uint8*)p_input_code+14);
            tod_rcv_msg_byte13 = *((uint8*)p_input_code+15);
            tod_rcv_msg_byte14 = *((uint8*)p_input_code+16);
            tod_rcv_msg_byte15 = *((uint8*)p_input_code+17);
            tod_rcv_msg_byte16 = *((uint8*)p_input_code+18);
            tod_rcv_msg_crc = *((uint8*)p_input_code+22);
            tod_rcv_msg_crc_error = 0;
            if(tod_rcv_msg_crc != _sys_usw_ptp_caculate_tod_crc(((uint8*)p_input_code)+2, 20))
            {
                tod_rcv_msg_crc_error = 1;
            }
        }
        else
        {
            tod_rcv_msg_byte0 = GetTsEngineTodInputCode(V, todRcvMsgByte0_f, &input_code);
            tod_rcv_msg_byte1 = GetTsEngineTodInputCode(V, todRcvMsgByte1_f, &input_code);
            tod_rcv_msg_byte2 = GetTsEngineTodInputCode(V, todRcvMsgByte2_f, &input_code);
            tod_rcv_msg_byte3 = GetTsEngineTodInputCode(V, todRcvMsgByte3_f, &input_code);
            tod_rcv_msg_byte4 = GetTsEngineTodInputCode(V, todRcvMsgByte4_f, &input_code);
            tod_rcv_msg_byte5 = GetTsEngineTodInputCode(V, todRcvMsgByte5_f, &input_code);
            tod_rcv_msg_byte6 = GetTsEngineTodInputCode(V, todRcvMsgByte6_f, &input_code);
            tod_rcv_msg_byte7 = GetTsEngineTodInputCode(V, todRcvMsgByte7_f, &input_code);
            tod_rcv_msg_byte12 = GetTsEngineTodInputCode(V, todRcvMsgByte12_f, &input_code);
            tod_rcv_msg_byte13 = GetTsEngineTodInputCode(V, todRcvMsgByte13_f, &input_code);
            tod_rcv_msg_byte14 = GetTsEngineTodInputCode(V, todRcvMsgByte14_f, &input_code);
            tod_rcv_msg_byte15 = GetTsEngineTodInputCode(V, todRcvMsgByte15_f, &input_code);
            tod_rcv_msg_byte16 = GetTsEngineTodInputCode(V, todRcvMsgByte16_f, &input_code);
            tod_rcv_msg_crc = GetTsEngineTodInputCode(V, todRcvMsgCrc_f, &input_code);
            tod_rcv_msg_crc_error = GetTsEngineTodInputCode(V, todRcvMsgCrcErr_f, &input_code);
        }
        

        SYS_PTP_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "tod_rcv_msg_byte: 2:0x%x 3:0x%x 4:0x%x 5:0x%x 6:0x%x 7:0x%x 12:0x%x 13:0x%x crc_error: %d\n",
                        tod_rcv_msg_byte2, tod_rcv_msg_byte3, tod_rcv_msg_byte4, tod_rcv_msg_byte5,
                        tod_rcv_msg_byte6, tod_rcv_msg_byte7, tod_rcv_msg_byte12, tod_rcv_msg_byte13, tod_rcv_msg_crc_error);

        if(tod_rcv_msg_crc_error)
        {
            goto OUT;
        }
        sal_memset(&tod_message, 0, sizeof(tod_message));
        tod_message.source = CTC_PTP_TIEM_INTF_TOD_1PPS;

        tod_message.u.tod_intf_message.msg_char0 = 'C';
        tod_message.u.tod_intf_message.msg_char1 = 'M';
        tod_message.u.tod_intf_message.msg_class = tod_rcv_msg_byte0;
        tod_message.u.tod_intf_message.msg_id = tod_rcv_msg_byte1;
        tod_message.u.tod_intf_message.msg_length = (tod_rcv_msg_byte2 << 8) + (tod_rcv_msg_byte3);
        tod_message.u.tod_intf_message.gps_second_time_of_week = (tod_rcv_msg_byte4 << 24) + (tod_rcv_msg_byte5 << 16)
        + (tod_rcv_msg_byte6 << 8) + (tod_rcv_msg_byte7);
        tod_message.u.tod_intf_message.gps_week = (tod_rcv_msg_byte12 << 8) + (tod_rcv_msg_byte13);
        tod_message.u.tod_intf_message.leap_second = tod_rcv_msg_byte14;
        tod_message.u.tod_intf_message.pps_status = tod_rcv_msg_byte15;
        tod_message.u.tod_intf_message.pps_accuracy = tod_rcv_msg_byte16;
        tod_message.u.tod_intf_message.crc = tod_rcv_msg_crc;
        tod_message.u.tod_intf_message.crc_error = tod_rcv_msg_crc_error;

        sal_memset(&input_ts, 0, sizeof(input_ts));
        input_ts.seconds = tod_message.u.tod_intf_message.gps_week * MCHIP_CAP(SYS_CAP_PTP_SECONDS_OF_EACH_WEEK) + MCHIP_CAP(SYS_CAP_PTP_TAI_TO_GPS_SECONDS)
        + tod_message.u.tod_intf_message.gps_second_time_of_week;

        /* 2. read captured ts from fifo*/
        if(DRV_FROM_AT(lchip))
        {
            cmd = DRV_IOR(TsEngineTodTs_t, DRV_ENTRY_FLAG);
        }
        else
        {
            cmd = DRV_IOR(TsEngineTodInputTs_t, DRV_ENTRY_FLAG);
        }
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &ptp_captured_ts));

        tod_message.captured_ts.seconds = GetTsEngineTodInputTs(V, captureAdjRcSecond_f, &ptp_captured_ts);
        tod_message.captured_ts.nanoseconds = GetTsEngineTodInputTs(V, captureAdjRcNs_f, &ptp_captured_ts);
        captured_ts.seconds = tod_message.captured_ts.seconds;
        captured_ts.nanoseconds = tod_message.captured_ts.nanoseconds;

        /* 3. calculate offset */
        SYS_PTP_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "Adjusted before captured_ts senocds %d nanoseconds %d 1pps_delay %d\n", captured_ts.seconds,  captured_ts.nanoseconds, p_usw_ptp_master[lchip]->tod_1pps_delay);
        if (p_usw_ptp_master[lchip]->tod_1pps_delay >= MCHIP_CAP(SYS_CAP_PTP_TOD_1PPS_DELAY))  /* tod_1pps_delay value bit 31 means delay < 0 */
        {
            if ((p_usw_ptp_master[lchip]->tod_1pps_delay - MCHIP_CAP(SYS_CAP_PTP_TOD_1PPS_DELAY) + captured_ts.nanoseconds) > MCHIP_CAP(SYS_CAP_PTP_NS_OR_NNS_VALUE))/*1pps delay between master and slave*/
            {
                captured_ts.seconds = captured_ts.seconds + 1;
                captured_ts.nanoseconds = p_usw_ptp_master[lchip]->tod_1pps_delay - MCHIP_CAP(SYS_CAP_PTP_TOD_1PPS_DELAY) + captured_ts.nanoseconds - MCHIP_CAP(SYS_CAP_PTP_NS_OR_NNS_VALUE);
            }
            else
            {
                captured_ts.nanoseconds = p_usw_ptp_master[lchip]->tod_1pps_delay - MCHIP_CAP(SYS_CAP_PTP_TOD_1PPS_DELAY) + captured_ts.nanoseconds;
            }
        }
        else
        {
            if (p_usw_ptp_master[lchip]->tod_1pps_delay > captured_ts.nanoseconds) /*1pps delay between master and slave*/
            {
                captured_ts.seconds = captured_ts.seconds ? (captured_ts.seconds - 1) : 0;
                captured_ts.nanoseconds = MCHIP_CAP(SYS_CAP_PTP_NS_OR_NNS_VALUE) + captured_ts.nanoseconds - p_usw_ptp_master[lchip]->tod_1pps_delay;
            }
            else
            {
                captured_ts.nanoseconds = captured_ts.nanoseconds - p_usw_ptp_master[lchip]->tod_1pps_delay;
            }
        }
        SYS_USW_REGISTER_WB_SYNC_EN(lchip, CTC_FEATURE_PTP, SYS_WB_APPID_PTP_SUBID_MASTER, 1);
        p_usw_ptp_master[lchip]->tod_1pps_delay = 0;
        SYS_PTP_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "Adjusted captured_ts af senocds %d nanoseconds %d\n", captured_ts.seconds,  captured_ts.nanoseconds);
        SYS_PTP_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "tod senocds %d\n", input_ts.seconds);
        if (input_ts.seconds > captured_ts.seconds) /*TS from ToD is second, no nano second*/
        {
            sal_memset(&offset, 0, sizeof(offset));
            offset.is_negative = 0;
            offset.seconds = input_ts.seconds - captured_ts.seconds;
            if (0 == captured_ts.nanoseconds)
            {
                offset.nanoseconds = 0;
            }
            else
            {
                offset.seconds = offset.seconds ? (offset.seconds - 1) : 0;
                offset.nanoseconds = MCHIP_CAP(SYS_CAP_PTP_NS_OR_NNS_VALUE) - captured_ts.nanoseconds;
            }
        }
        else
        {
            sal_memset(&offset, 0, sizeof(offset));
            offset.is_negative = 1;
            offset.seconds = captured_ts.seconds - input_ts.seconds;
            offset.nanoseconds = captured_ts.nanoseconds;
        }
        SYS_PTP_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "offset senocds %d nanoseconds %d is_negative %d\n", offset.seconds, offset.nanoseconds, offset.is_negative);
        /* 4. adjust offset */
        if ((0x01 == tod_message.u.tod_intf_message.msg_class) && (0x20 == tod_message.u.tod_intf_message.msg_id )\
            && (p_usw_ptp_master[lchip]->tod_1pps_thrd != CTC_MAX_UINT32_VALUE))/*time message*/
        {
            ret = MCHIP_PTP(lchip)->adjust_clock_offset? MCHIP_PTP(lchip)->adjust_clock_offset(lchip, (void*)&offset)
            : _sys_usw_ptp_adjust_clock_offset(lchip, &offset);
            if (CTC_E_NONE != ret)
            {
                /*if adjust error need clear code rdy*/
                goto OUT;
            }
        }

        /* 5. call Users callback to return code message */
        CTC_ERROR_RETURN(sys_usw_interrupt_get_event_cb(lchip, CTC_EVENT_PTP_INPUT_CODE_READY, &cb));
        if (cb)
        {
            (void)cb(gchip, &tod_message);
        }

    }
    SYS_PTP_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "tod interface input message,msg_char0:%d, msg_char1:%d, msg_class:%d, msg_id:%d, msg_length:%d, "
                                          "gps_week:%d, gps_second_time_of_week:%u, leap_second:%d, pps_status:%d, pps_accuracy:%d, "
                                          "crc_error:%d, crc:%d, clock_src:%d, clock_src_status:%d, monitor_alarm:%d\n",
                                            tod_message.u.tod_intf_message.msg_char0,
                                            tod_message.u.tod_intf_message.msg_char1,
                                            tod_message.u.tod_intf_message.msg_class,
                                            tod_message.u.tod_intf_message.msg_id,
                                            tod_message.u.tod_intf_message.msg_length,
                                            tod_message.u.tod_intf_message.gps_week,
                                            tod_message.u.tod_intf_message.gps_second_time_of_week,
                                            tod_message.u.tod_intf_message.leap_second,
                                            tod_message.u.tod_intf_message.pps_status,
                                            tod_message.u.tod_intf_message.pps_accuracy,
                                            tod_message.u.tod_intf_message.crc_error,
                                            tod_message.u.tod_intf_message.crc,
                                            tod_message.u.tod_intf_message.clock_src,
                                            tod_message.u.tod_intf_message.clock_src_status,
                                            tod_message.u.tod_intf_message.monitor_alarm);

    SYS_PTP_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "tod interface capture message,s:%d, ns:%d\n",
                                            tod_message.captured_ts.seconds,
                                            tod_message.captured_ts.nanoseconds);
OUT:
    if(!DRV_FROM_AT(lchip))
    {
        SetTsEngineTodInputCode(V, todCodeInRdy_f, &input_code, 0);
        cmd = DRV_IOW(TsEngineTodInputCode_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &input_code));
    }
    return CTC_E_NONE;
}

/**
 @brief  PTP TOD code ready polling
*/
void
sys_usw_ptp_polling_tod_code_rdy(void* param)
{
    uint32 cmd = 0;
    TsEngineTodInputCode_m input_code;
    uint8 lchip = (uintptr)param;
    uint32 fld_val = 0;

    SYS_LCHIP_CHECK_ACTIVE_START_THREAD(lchip);
    while(1)
    {
        SYS_LCHIP_CHECK_ACTIVE_IN_THREAD(lchip);
        SYS_CHIP_CHECK_RESET_HW_IN_THREAD(lchip);

       /* 1. read input code */
       sal_memset(&input_code, 0, sizeof(input_code));
       cmd = DRV_IOR(TsEngineTodCfg_t, TsEngineTodCfg_todTsCaptureEn_f);
       DRV_FIELD_IOCTL(lchip, 0, cmd, &fld_val);
       cmd = DRV_IOR(TsEngineTodInputCode_t, DRV_ENTRY_FLAG);
       DRV_IOCTL(lchip, 0, cmd, &input_code);
       if ((1 != GetTsEngineTodInputCode(V, todCodeInRdy_f, &input_code)) || (0 == fld_val)) /*message has received already*/
       {
           SYS_PTP_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "error return no code in rdy\n");
           sal_task_sleep(300);
           continue;
       }

        sys_usw_ptp_tod_code_rdy(lchip, 0, &input_code);
        sal_task_sleep(300);
    }

    return ;
}

/** @brief  PTP TOD code ready isr*/
int32
sys_usw_ptp_isr_tod_code_rdy(uint8 lchip, uint32 intr, void* p_data)
{
    uint32 cmd = 0;
    TsEngineTodInputCode_m input_code;

    SYS_PTP_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    SYS_PTP_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "tod interface code ready!\n");
    SYS_PTP_INIT_CHECK();

    /* 1. read input code */
    sal_memset(&input_code, 0, sizeof(input_code));
    cmd = DRV_IOR(TsEngineTodInputCode_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &input_code));
    if (1 != GetTsEngineTodInputCode(V, todCodeInRdy_f, &input_code)) /*message has received already*/
    {
        return CTC_E_NONE;
    }

    CTC_ERROR_RETURN(sys_usw_ptp_tod_code_rdy(lchip, 0, &input_code));

    return CTC_E_NONE;
}

/** @brief  PTP TOD code ready isr*/
int32
sys_usw_ptp_isr_tod_code_rdy_from_mcu(uint8 lchip, uint8 isr_type, void* p_data)
{
    uint8 tod_code[SYS_PTP_TOD_MESSAGE_LENTH] = {0};

    SYS_PTP_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    SYS_PTP_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "tod interface code ready form misc mcu!\n");
    SYS_PTP_INIT_CHECK();


    /*from arctic must get input code from share memory unconditionally*/
    if(DRV_FROM_AT(lchip))
    {
        if (MCHIP_EUNIT(lchip) && MCHIP_EUNIT(lchip)->get_cfg)
        {
            MCHIP_EUNIT(lchip)->get_cfg(lchip, SYS_EUNIT_CFG_TOD, (uint32*)tod_code);
        }
    }

    CTC_ERROR_RETURN(sys_usw_ptp_tod_code_rdy(lchip, p_usw_ptp_master[lchip]->tod_1pps_flex_en ? 1 : 0, tod_code));

    return CTC_E_NONE;
}


/**
 @brief  PTP syncPulse in isr
*/
int32
sys_usw_ptp_isr_sync_pulse_in(uint8 lchip, uint32 intr, void* p_data)
{
    uint8 gchip = 0;
    uint32 cmd = 0;
    uint8 index = 0;
    uint32 tbl_id_capture = 0;
    ds_t ptp_captured_adj_frc;
    ctc_ptp_time_t captured_ts;
    CTC_INTERRUPT_EVENT_FUNC cb = NULL;

    index = (intr == SYS_INTR_FUNC_PTP_SYNC_PULSE_IN) ? 0 : 1;
    if(p_usw_ptp_master[lchip]->sync_mode[index] != CTC_PTP_INTF_MODE_1PPS_ONLY)
    {
        return CTC_E_NONE;
    }
    /* read input code */
    if (DRV_FROM_AT(lchip))
    {
        tbl_id_capture = TsSyncIntfCaptureTs_t;
    }
    else
    {
        tbl_id_capture = TsEngineSyncIntfInputTs_t;
    }

    sal_memset(&ptp_captured_adj_frc, 0, sizeof(ptp_captured_adj_frc));
    sal_memset(&captured_ts, 0, sizeof(captured_ts));

    cmd = DRV_IOR(tbl_id_capture, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &ptp_captured_adj_frc));

    if (DRV_FROM_AT(lchip) && (GetTsSyncIntfCaptureTs(V, captureTsValid_f, &ptp_captured_adj_frc) == 0))
    {
        return CTC_E_NONE;
    }

    captured_ts.seconds = GetTsEngineSyncIntfInputTs(V, captureAdjRcSecond_f, &ptp_captured_adj_frc);
    captured_ts.nanoseconds = GetTsEngineSyncIntfInputTs(V, captureAdjRcNs_f, &ptp_captured_adj_frc);

    SYS_PTP_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    SYS_PTP_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "ts.seconds:%d  ts.nanoseconds:%d\n", captured_ts.seconds, captured_ts.nanoseconds);

    /* call Users callback to return code message */
    CTC_ERROR_RETURN(sys_usw_interrupt_get_event_cb(lchip, CTC_EVENT_PTP_INPUT_CODE_READY, &cb));
    if (cb)
    {
        (void)cb(gchip, &captured_ts);
    }

    return CTC_E_NONE;
}

/**
 @brief  PTP Sync Interface code ready isr
*/
int32
sys_usw_ptp_isr_sync_code_rdy(uint8 lchip, uint32 intr, void* p_data)
{
    int32 ret = CTC_E_NONE;
    uint8 gchip = 0;
    uint32 cmd = 0;
    uint32 data88_to64 = 0;
    uint32 data63_to32 = 0;
    uint32 data31_to0 = 0;
    uint8 index = 0;
    uint32 tbl_id_input = 0;
    uint32 tbl_id_capture = 0;
    ctc_ptp_rx_ts_message_t sync_message;
    TsEngineSyncIntfInputCode_m input_code;
    TsEngineSyncIntfInputTs_m ptp_captured_adj_frc;
    ctc_ptp_time_t captured_ts;
    ctc_ptp_time_t input_ts;
    ctc_ptp_time_t offset;
    uint64 input_nanoseconds = 0;
    uint64 captured_nanoseconds = 0;
    uint64 offset_nanoseconds = 0;
    CTC_INTERRUPT_EVENT_FUNC cb = NULL;

    index = (intr == SYS_INTR_FUNC_PTP_SYNC_CODE_IN_RDY)? 0 : 1;
    if(p_usw_ptp_master[lchip]->sync_mode[index] != CTC_PTP_INTF_MODE_INPUT)
    {
        return CTC_E_NONE;
    }

    if (DRV_FROM_AT(lchip))
    {
        tbl_id_input = TsSyncIntfInputCode_t;
        tbl_id_capture = TsSyncIntfCaptureTs_t;
    }
    else
    {
        tbl_id_input = TsEngineSyncIntfInputCode_t;
        tbl_id_capture = TsEngineSyncIntfInputTs_t;
    }
    sal_memset(&ptp_captured_adj_frc, 0, sizeof(ptp_captured_adj_frc));
    sal_memset(&captured_ts, 0, sizeof(captured_ts));
    sal_memset(&input_ts, 0, sizeof(input_ts));
    sal_memset(&offset, 0, sizeof(offset));

    SYS_PTP_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    SYS_PTP_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "sync interface code ready!\n");
    SYS_PTP_INIT_CHECK();

    CTC_ERROR_RETURN(sys_usw_get_gchip_id(lchip, &gchip));

    /* 1. read input code */
    sal_memset(&input_code, 0, sizeof(input_code));
    cmd = DRV_IOR(tbl_id_input, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &input_code));
    if (1 != GetTsEngineSyncIntfInputCode(V, syncCodeInRdy_f, &input_code)) /*timecode has received already*/
    {
        return CTC_E_NONE;
    }

    /*get timecode*/
    GetTsEngineSyncIntfInputCode(A, data88To64_f, &input_code, &data88_to64);
    GetTsEngineSyncIntfInputCode(A, data63To32_f, &input_code, &data63_to32);
    GetTsEngineSyncIntfInputCode(A, data31To0_f, &input_code, &data31_to0);

    sal_memset(&sync_message, 0, sizeof(sync_message));
    sync_message.source = index? CTC_PTP_TIEM_INTF_SYNC_PULSE_1 : CTC_PTP_TIEM_INTF_SYNC_PULSE;

    sync_message.u.sync_intf_message.seconds = (data88_to64 & 0xffffff) << 24 | (data63_to32 & 0xffffff00) >> 8;
    sync_message.u.sync_intf_message.nanoseconds = (data63_to32 & 0xff) << 24 | (data31_to0 & 0xffffff00) >> 8;
    sync_message.u.sync_intf_message.lock = data88_to64 >> 24;
    sync_message.u.sync_intf_message.accuracy = data31_to0 & 0xff;
    sync_message.u.sync_intf_message.crc_error = GetTsEngineSyncIntfInputCode(V, crcErr_f, &input_code);
    sync_message.u.sync_intf_message.crc = GetTsEngineSyncIntfInputCode(V, crc_f, &input_code);
    sync_message.domain_id = index;
    input_ts.seconds = sync_message.u.sync_intf_message.seconds;
    input_ts.nanoseconds = sync_message.u.sync_intf_message.nanoseconds;

    cmd = DRV_IOR(tbl_id_capture, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &ptp_captured_adj_frc));
    if (DRV_FROM_AT(lchip) && (GetTsSyncIntfCaptureTs(V, captureTsValid_f, &ptp_captured_adj_frc) == 0))
    {
        return CTC_E_NONE;
    }
    sync_message.captured_ts.seconds = GetTsEngineSyncIntfInputTs(V, captureAdjRcSecond_f, &ptp_captured_adj_frc);
    sync_message.captured_ts.nanoseconds = GetTsEngineSyncIntfInputTs(V, captureAdjRcNs_f, &ptp_captured_adj_frc);
    captured_ts.seconds = sync_message.captured_ts.seconds;
    captured_ts.nanoseconds = sync_message.captured_ts.nanoseconds;

    /* 3. calculate offset */
    input_nanoseconds = ((uint64)input_ts.seconds) * MCHIP_CAP(SYS_CAP_PTP_NS_OR_NNS_VALUE) + input_ts.nanoseconds;
    captured_nanoseconds = ((uint64)captured_ts.seconds) * MCHIP_CAP(SYS_CAP_PTP_NS_OR_NNS_VALUE) + captured_ts.nanoseconds;
    if (input_nanoseconds >= captured_nanoseconds)
    {
        offset.is_negative = 0;
        offset_nanoseconds = input_nanoseconds - captured_nanoseconds;
    }
    else
    {
        offset.is_negative = 1;
        offset_nanoseconds = captured_nanoseconds - input_nanoseconds;
    }

    offset.seconds = offset_nanoseconds / MCHIP_CAP(SYS_CAP_PTP_NS_OR_NNS_VALUE);
    offset.nanoseconds = offset_nanoseconds % MCHIP_CAP(SYS_CAP_PTP_NS_OR_NNS_VALUE);
    offset.domain_id = index;

    SYS_PTP_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "sync interface offset message,is_negative:%d, s:%d, ns:%d\n",
                                                offset.is_negative,
                                                offset.seconds,
                                                offset.nanoseconds);

    /* 4. adjust offset */
    ret = MCHIP_PTP(lchip)->adjust_clock_offset? MCHIP_PTP(lchip)->adjust_clock_offset(lchip, (void*)&offset)
    :_sys_usw_ptp_adjust_clock_offset(lchip, &offset);
    if (CTC_E_NONE != ret )
    {
        goto Err;
    }

    /* 5. call Users callback to return code message */
    CTC_ERROR_RETURN(sys_usw_interrupt_get_event_cb(lchip, CTC_EVENT_PTP_INPUT_CODE_READY, &cb));
    if (cb)
    {
        (void)cb(gchip, &sync_message);
    }

    SYS_PTP_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "sync interface input message,s:%d, ns:%d, lock:%d, acc:%d, crc_err:%d, crc:%d\n",
                                            sync_message.u.sync_intf_message.seconds,
                                            sync_message.u.sync_intf_message.nanoseconds,
                                            sync_message.u.sync_intf_message.lock,
                                            sync_message.u.sync_intf_message.accuracy,
                                            sync_message.u.sync_intf_message.crc_error,
                                            sync_message.u.sync_intf_message.crc);

    SYS_PTP_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "sync interface capture message,s:%d, ns:%d\n",
                                            sync_message.captured_ts.seconds,
                                            sync_message.captured_ts.nanoseconds);

Err:
    /* 6. clear ready flag*/
    SetTsEngineSyncIntfInputCode(V, syncCodeInRdy_f, &input_code, 0);
    cmd = DRV_IOW(tbl_id_input, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &input_code));

    return CTC_E_NONE;
}

/**
 @brief  PTP Sync Interface code acc isr
*/
int32
sys_usw_ptp_isr_sync_code_acc(uint8 lchip, uint32 intr, void* p_data)
{
    return CTC_E_NONE;
}

STATIC int32
_sys_usw_ptp_dump_db(uint8 lchip, sal_file_t p_f, ctc_global_dump_db_t* p_dump_param)
{
    SYS_DUMP_DB_LOG(p_f, "%s\n", "# Ptp");
    SYS_DUMP_DB_LOG(p_f, "%s\n", "{");
    SYS_DUMP_DB_LOG(p_f, "%s\n", "Master config:");
    SYS_DUMP_DB_LOG(p_f, "%s\n", "------------------------------------------------------------");
    SYS_DUMP_DB_LOG(p_f, "%-30s:%u\n","quanta",p_usw_ptp_master[lchip]->quanta);
    SYS_DUMP_DB_LOG(p_f, "%-30s:%u\n","intf_selected",p_usw_ptp_master[lchip]->intf_selected);
    SYS_DUMP_DB_LOG(p_f, "%-30s:%u\n","cache_aging_time",p_usw_ptp_master[lchip]->cache_aging_time);
    SYS_DUMP_DB_LOG(p_f, "%-30s:%u\n","device_type",p_usw_ptp_master[lchip]->device_type);
    SYS_DUMP_DB_LOG(p_f, "%-30s:%u\n","tod_1pps_duty",p_usw_ptp_master[lchip]->tod_1pps_duty);
    SYS_DUMP_DB_LOG(p_f, "%-30s:%u\n","tod_1pps_delay",p_usw_ptp_master[lchip]->tod_1pps_delay);
    SYS_DUMP_DB_LOG(p_f, "%-30s:%u\n","tod_1pps_delay_nano_ns",p_usw_ptp_master[lchip]->tod_1pps_delay_nano_ns);
    SYS_DUMP_DB_LOG(p_f, "%s\n", "------------------------------------------------------------");
    SYS_DUMP_DB_LOG(p_f, "%s\n", "}");

    return CTC_E_NONE;
}

#define __6_PTP_API__
/**
 @brief Set ptp property
*/
int32
sys_usw_ptp_set_global_property(uint8 lchip, ctc_ptp_global_prop_t property, uint32 value)
{
    int32 ret = CTC_E_NONE;
    uint32 field_val = 0;
    uint32 cmd = 0;

    /*check*/
    SYS_PTP_INIT_CHECK();

    /*debug info*/
    SYS_PTP_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    SYS_PTP_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "Set ptp global property, property:%d, value:%d\n", property, value);

    /*set global property*/
    switch (property)
    {
        case CTC_PTP_GLOBAL_PROP_CACHE_AGING_TIME:
        {
            CTC_MAX_VALUE_CHECK(value, 0xFFFF);

            if(DRV_FROM_TMM(lchip))
            {
                return CTC_E_NOT_SUPPORT;
            }

            PTP_LOCK;

            SYS_USW_REGISTER_WB_SYNC_EN(lchip, CTC_FEATURE_PTP, SYS_WB_APPID_PTP_SUBID_MASTER, 1);
            ret = _sys_usw_ptp_set_cache_aging_time(lchip, value);

            PTP_UNLOCK;

            break;
        }
        case CTC_PTP_GLOBAL_PROP_SYNC_OR_TOD_INPUT_SELECT:
        {
            CTC_MAX_VALUE_CHECK(value, (MAX_CTC_PTP_INTF_SELECT - 1));

            PTP_LOCK;

            SYS_USW_REGISTER_WB_SYNC_EN(lchip, CTC_FEATURE_PTP, SYS_WB_APPID_PTP_SUBID_MASTER, 1);

            ret = MCHIP_PTP(lchip)->set_input_select? MCHIP_PTP(lchip)->set_input_select(lchip, value)
            : _sys_usw_ptp_set_sync_of_tod_input_select(lchip, value);

            PTP_UNLOCK;

            break;
        }
        case CTC_PTP_GLOBAL_PROP_PORT_BASED_PTP_EN:
        {
            field_val = value ? 0 : 1;
            cmd = DRV_IOW(IpeIntfMapperCtl_t, IpeIntfMapperCtl_ptpUseVlanIndex_f);
            CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &field_val));
            break;
        }
        case CTC_PTP_GLOBAL_PROP_SEQ_ID_FROM_CPU:
        {
            field_val = value ? 1 : 0;
            cmd = DRV_IOW(EpeHdrAdjustCtl_t, EpeHdrAdjustCtl_ptpSeqFromHdrEn_f);
            CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &field_val));
            break;
        }
        default:
        {
            return CTC_E_INVALID_PARAM;
        }
    }

    return ret;
}

/**
 @brief Get ptp property
*/
int32
sys_usw_ptp_get_global_property(uint8 lchip, ctc_ptp_global_prop_t property, uint32* value)
{
    int32 ret = CTC_E_NONE;
    uint32 cmd = 0;

    /*check*/
    SYS_PTP_INIT_CHECK();
    CTC_PTR_VALID_CHECK(value);

    /*debug info*/
    SYS_PTP_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    SYS_PTP_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "Get ptp global property, property:%d, value:%d\n", property, *value);

    switch (property)
    {
        case CTC_PTP_GLOBAL_PROP_CACHE_AGING_TIME:
        {
            PTP_LOCK;

            ret = _sys_usw_ptp_get_cache_aging_time(lchip, value);

            PTP_UNLOCK;

            break;
        }
        case CTC_PTP_GLOBAL_PROP_SYNC_OR_TOD_INPUT_SELECT:
        {
            PTP_LOCK;

            ret = _sys_usw_ptp_get_sync_of_tod_input_select(lchip, value);

            PTP_UNLOCK;

            break;
        }
        case CTC_PTP_GLOBAL_PROP_PORT_BASED_PTP_EN:
        {
            cmd = DRV_IOR(IpeIntfMapperCtl_t, IpeIntfMapperCtl_ptpUseVlanIndex_f);
            CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, value));
            *value = *value ? 0 : 1;
            break;
        }
        case CTC_PTP_GLOBAL_PROP_SEQ_ID_FROM_CPU:
        {
            cmd = DRV_IOR(EpeHdrAdjustCtl_t, EpeHdrAdjustCtl_ptpSeqFromHdrEn_f);
            CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &value));
            break;
        }
        default:
        {
            return CTC_E_INVALID_PARAM;
        }
    }

    return ret;
}

/**
 @brief Get timestamp from free running clock
*/
int32
sys_usw_ptp_get_clock_timestamp(uint8 lchip, ctc_ptp_time_t* timestamp)
{
    int32 ret = CTC_E_NONE;

    /*check*/
    SYS_PTP_INIT_CHECK();
    CTC_PTR_VALID_CHECK(timestamp);
    CTC_MAX_VALUE_CHECK(timestamp->domain_id, MCHIP_CAP(SYS_CAP_PTP_MAX_DOMAIN_ID));

    /*debug info*/
    SYS_PTP_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    SYS_PTP_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "Get ptp clock timestamp, lchip:%d\n", lchip);

    PTP_LOCK;
    ret = MCHIP_PTP(lchip)->get_clock_timestamp? MCHIP_PTP(lchip)->get_clock_timestamp(lchip, (void*)timestamp)
    : _sys_usw_ptp_get_clock_timestamp(lchip, timestamp);
    PTP_UNLOCK;

    return ret;
}

/**
 @brief Adjust offset for free running clock
*/
int32
sys_usw_ptp_adjust_clock_offset(uint8 lchip, ctc_ptp_time_t* offset)
{
    int32 ret = CTC_E_NONE;

    /*check*/
    SYS_PTP_INIT_CHECK();
    CTC_PTR_VALID_CHECK(offset);

    /*debug info*/
    SYS_PTP_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    SYS_PTP_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "Adjust ptp clock offset, lchip:%d, seconds:%d, nanoseconds:%d, is_negative:%d\n", \
                                                                                lchip, offset->seconds, offset->nanoseconds, offset->is_negative);

    if (offset->nanoseconds >= MCHIP_CAP(SYS_CAP_PTP_NS_OR_NNS_VALUE))
    {
        return CTC_E_INVALID_PARAM;
    }
    CTC_MAX_VALUE_CHECK(offset->domain_id, MCHIP_CAP(SYS_CAP_PTP_MAX_DOMAIN_ID));
    
    PTP_LOCK;
    ret = MCHIP_PTP(lchip)->adjust_clock_offset? MCHIP_PTP(lchip)->adjust_clock_offset(lchip, (void*)offset)
    : _sys_usw_ptp_adjust_clock_offset(lchip, offset);
    PTP_UNLOCK;

    return ret;
}

/**
 @brief Set drift for free running clock
*/
int32
sys_usw_ptp_set_clock_drift(uint8 lchip, ctc_ptp_time_t* p_drift)
{
    int32 ret = CTC_E_NONE;

    /*check*/
    SYS_PTP_INIT_CHECK();
    CTC_PTR_VALID_CHECK(p_drift);

    /*debug info*/
    SYS_PTP_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    SYS_PTP_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "Set ptp clock drift, lchip:%d, nanoseconds:%d, is_negative:%d\n", \
                                                                                lchip, p_drift->nanoseconds, p_drift->is_negative);

    if (p_drift->nanoseconds >= MCHIP_CAP(SYS_CAP_PTP_NS_OR_NNS_VALUE))
    {
        return CTC_E_INVALID_PARAM;
    }

    PTP_LOCK;

    SYS_USW_REGISTER_WB_SYNC_EN(lchip, CTC_FEATURE_PTP, SYS_WB_APPID_PTP_SUBID_MASTER, 1);
    ret = MCHIP_PTP(lchip)->set_clock_drift? MCHIP_PTP(lchip)->set_clock_drift(lchip, (void*)p_drift) : \
    _sys_usw_ptp_set_clock_drift(lchip, p_drift);

    PTP_UNLOCK;

    return ret;
}

/**
 @brief Get drift for free running clock
*/
int32
sys_usw_ptp_get_clock_drift(uint8 lchip, ctc_ptp_time_t* p_drift)
{
    int32 ret = CTC_E_NONE;

    /*check*/
    SYS_PTP_INIT_CHECK();
    CTC_PTR_VALID_CHECK(p_drift);

    /*debug info*/
    SYS_PTP_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    SYS_PTP_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "Get ptp clock drift, lchip:%d\n", lchip);

    PTP_LOCK;

    ret = MCHIP_PTP(lchip)->get_clock_drift? MCHIP_PTP(lchip)->get_clock_drift(lchip, (void*)p_drift) : \
    _sys_usw_ptp_get_clock_drift(lchip, p_drift);

    PTP_UNLOCK;

    return ret;
}

/**
 @brief Set PTP device type
*/
int32
sys_usw_ptp_set_device_type(uint8 lchip, ctc_ptp_device_type_t device_type)
{
    int32 ret = CTC_E_NONE;

    /*check*/
    SYS_PTP_INIT_CHECK();

    /*debug info*/
    SYS_PTP_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    SYS_PTP_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "Set device type, lchip:%d, device_type:%d\n", lchip, device_type);

    CTC_MAX_VALUE_CHECK(device_type, (MAX_CTC_PTP_DEVICE - 1));

    PTP_LOCK;

    SYS_USW_REGISTER_WB_SYNC_EN(lchip, CTC_FEATURE_PTP, SYS_WB_APPID_PTP_SUBID_MASTER, 1);
    ret = MCHIP_PTP(lchip)->set_device_type? MCHIP_PTP(lchip)->set_device_type(lchip, device_type)
    : _sys_usw_ptp_set_device_type(lchip, device_type);

    p_usw_ptp_master[lchip]->device_type = device_type;
    PTP_UNLOCK;

    return ret;
}

/**
 @brief Set PTP device type
*/
int32
sys_usw_ptp_get_device_type(uint8 lchip, ctc_ptp_device_type_t* device_type)
{
    int32 ret = CTC_E_NONE;

    /*check*/
    SYS_PTP_INIT_CHECK();
    CTC_PTR_VALID_CHECK(device_type);

    /*debug info*/
    SYS_PTP_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    PTP_LOCK;

    ret = _sys_usw_ptp_get_device_type(lchip, device_type);

    PTP_UNLOCK;

    return ret;
}

/**
 @brief Add ptp clock type
*/
int32
sys_usw_ptp_add_device_clock(uint8 lchip, ctc_ptp_clock_t* clock)
{
    int32 ret = CTC_E_NONE;

    /*check*/
    SYS_PTP_INIT_CHECK();
    CTC_PTR_VALID_CHECK(clock);
    CTC_VALUE_RANGE_CHECK(clock->clock_id, SYS_PTP_USER_CLOCK_ID_MIN, SYS_PTP_USER_CLOCK_ID_MAX);
    if (clock->domain_id == 1)
    {
        CTC_VALUE_RANGE_CHECK(clock->cpu_reason, CTC_PKT_CPU_REASON_CUSTOM_BASE, CTC_PKT_CPU_REASON_MAX_COUNT - 1);
    }

    /*debug info*/
    SYS_PTP_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    SYS_PTP_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "Add ptp device clock type, clock_id:%d\n", clock->clock_id);

    PTP_LOCK;

    ret = MCHIP_PTP(lchip)->add_device_clock ? MCHIP_PTP(lchip)->add_device_clock(lchip, (void*)clock)
    : _sys_usw_ptp_add_device_clock(lchip, clock);

    PTP_UNLOCK;

    return ret;
}

/**
 @brief Remove ptp clock type
*/
int32
sys_usw_ptp_remove_device_clock(uint8 lchip, ctc_ptp_clock_t* clock)
{
    int32 ret = CTC_E_NONE;

    /*check*/
    SYS_PTP_INIT_CHECK();
    CTC_PTR_VALID_CHECK(clock);
    CTC_VALUE_RANGE_CHECK(clock->clock_id, SYS_PTP_USER_CLOCK_ID_MIN, SYS_PTP_USER_CLOCK_ID_MAX);

    /*debug info*/
    SYS_PTP_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    SYS_PTP_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "Remove ptp device clock type, clock_id:%d\n", clock->clock_id);

    PTP_LOCK;

    ret = MCHIP_PTP(lchip)->remove_device_clock? MCHIP_PTP(lchip)->remove_device_clock(lchip, (void*)clock)
    : _sys_usw_ptp_remove_device_clock(lchip, clock);

    PTP_UNLOCK;

    return ret;
}

/**
 @brief Set adjust delay for PTP message delay correct
*/
int32
sys_usw_ptp_set_adjust_delay(uint8 lchip, uint32 gport, ctc_ptp_adjust_delay_type_t type, int64 value)
{
    uint64 tmp_value=0;
    int32 ret = CTC_E_NONE;

    /*check*/
    SYS_PTP_INIT_CHECK();
    SYS_MAX_PHY_PORT_CHECK(gport);

    /*debug info*/
    SYS_PTP_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    SYS_PTP_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "Set ptp adjust delay, gport:%d, type:%d, value:%"PRId64"\n", gport, type, value);

    CTC_MAX_VALUE_CHECK(type, (MAX_CTC_PTP_ADJUST_DELAY - 1));

    switch (type)
    {
        case CTC_PTP_ADJUST_DELAY_INGRESS_LATENCY:
        case CTC_PTP_ADJUST_DELAY_EGRESS_LATENCY:
        {
            if (value < 0)
            {
                return CTC_E_INVALID_PARAM;
            }
            CTC_MAX_VALUE_CHECK(value, DRV_FROM_AT(lchip)?0x3FFFFFFFLL:0xFFFFLL);

            break;
        }
        case CTC_PTP_ADJUST_DELAY_INGRESS_ASYMMETRY:
        case CTC_PTP_ADJUST_DELAY_EGRESS_ASYMMETRY:
        {
            tmp_value = value >= 0? value : -value;

                if (DRV_FROM_AT(lchip) && tmp_value > 0xFFFFF)
                {
                    return CTC_E_INVALID_PARAM;
                }
                else if (((tmp_value >> 32) & 0xFFFFFFFFLL) > 0xF)
                {
                    return CTC_E_INVALID_PARAM;
                }

            break;
        }
        case CTC_PTP_ADJUST_DELAY_PATH_DELAY:
        {
            if (((((value >> 32) & 0xFFFFFFFFLL) > 0xF)&&(!DRV_FROM_AT(lchip))) || (value < 0))
            {
                return CTC_E_INVALID_PARAM;
            }
            if (DRV_FROM_AT(lchip))
            {
                CTC_MAX_VALUE_CHECK(value, 0x3FFFFFFFLL);
            }

            break;
        }
        default:
        {
            return CTC_E_INVALID_PARAM;
        }
    }

    PTP_LOCK;
    ret = MCHIP_PTP(lchip)->set_ajust_delay? MCHIP_PTP(lchip)->set_ajust_delay(lchip, gport, (uint8)type, value)
    : _sys_usw_ptp_set_adjust_delay(lchip, gport, type, value);

    PTP_UNLOCK;

    return ret;
}

/**
 @brief Set adjust delay for PTP message delay correct
*/
int32
sys_usw_ptp_get_adjust_delay(uint8 lchip, uint32 gport, ctc_ptp_adjust_delay_type_t type, int64* value)
{
    int32 ret = CTC_E_NONE;

    /*check*/
    SYS_PTP_INIT_CHECK();
    SYS_MAX_PHY_PORT_CHECK(gport);
    CTC_PTR_VALID_CHECK(value);

    /*debug info*/
    SYS_PTP_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    SYS_PTP_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "Get ptp adjust delay, gport:%d, type:%d\n", gport, type);

    CTC_MAX_VALUE_CHECK(type, (MAX_CTC_PTP_ADJUST_DELAY - 1));

    PTP_LOCK;

    ret = _sys_usw_ptp_get_adjust_delay(lchip, gport, type, value);

    PTP_UNLOCK;

    return ret;
}

/**
 @brief  Get timestamp captured by local clock
*/
int32
sys_usw_ptp_get_captured_ts(uint8 lchip, ctc_ptp_capured_ts_t* p_captured_ts)
{
#if 1
    int32 ret = CTC_E_NONE;
    sys_ptp_capured_ts_t get_ts;
    ctc_ptp_captured_src_t ctc_src = 0;
    uint8 source = 0;

    /*check*/
    SYS_PTP_INIT_CHECK();
    CTC_PTR_VALID_CHECK(p_captured_ts);

    /*debug info*/
    SYS_PTP_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    SYS_PTP_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "Get captured ts, lchip:%d, type:%d\n", lchip, p_captured_ts->type);

    if (CTC_PTP_CAPTURED_TYPE_RX == p_captured_ts->type) /*read captured rx ts triggered by syncPulse or 1PPS*/
    {
        SYS_PTP_RX_SEQ_ID_CHECK(p_captured_ts->seq_id);

        ctc_src = p_captured_ts->u.captured_src;
        CTC_ERROR_GOTO(_sys_usw_ptp_map_captured_src(lchip, &ctc_src, &source, 1), ret, out);
        sal_memset(&get_ts, 0, sizeof(get_ts));
        get_ts.lport_or_source = source;
        get_ts.seq_id = p_captured_ts->seq_id;
    }
    else if (CTC_PTP_CAPTURED_TYPE_TX == p_captured_ts->type) /*read captured tx ts triggered by packet transmit*/
    {
        /* Duet2 do not support capture tx */
        ret = CTC_E_INVALID_PARAM;
        goto out;
    }
    else
    {
        ret = CTC_E_INVALID_PARAM;
        goto out;
    }

    PTP_LOCK;
    SYS_USW_REGISTER_WB_SYNC_EN(lchip, CTC_FEATURE_PTP, SYS_WB_APPID_PTP_SUBID_MASTER, 1);
    CTC_ERROR_GOTO(_sys_usw_ptp_get_captured_ts(lchip, p_captured_ts->type, &get_ts), ret, out1);
    p_captured_ts->ts.seconds = get_ts.ts.seconds;
    p_captured_ts->ts.nanoseconds = get_ts.ts.nanoseconds;
    PTP_UNLOCK;

    return CTC_E_NONE;

out1:
    PTP_UNLOCK;
out:
    return ret;
#else
    return CTC_E_NONE;
#endif
}

/**
 @brief  Set sync interface config
*/
int32
sys_usw_ptp_set_sync_intf(uint8 lchip, ctc_ptp_sync_intf_cfg_t* p_config)
{
    int32 ret = CTC_E_NONE;
    uint32 value = 0;

    /*check*/
    SYS_PTP_INIT_CHECK();
    CTC_PTR_VALID_CHECK(p_config);
    CTC_MAX_VALUE_CHECK(p_config->domain_id, MCHIP_CAP(SYS_CAP_PTP_MAX_DOMAIN_ID));
    CTC_MAX_VALUE_CHECK(p_config->mode, CTC_PTP_INTF_MODE_MAX);

    if(p_config->mode == CTC_PTP_INTF_MODE_DISABLE)
    {
        return CTC_E_INVALID_PARAM;
    }

    /*debug info*/
    SYS_PTP_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    SYS_PTP_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "Set sync interface config, lchip:%d\n", lchip);

    if ((p_config->sync_clock_hz > SYS_PTP_MAX_SYNC_CLOCK_FREQUENCY_HZ) || (p_config->sync_clock_hz < 1))
    {
        return CTC_E_INVALID_PARAM;
    }

    if ((p_config->sync_pulse_hz > MCHIP_CAP(SYS_CAP_PTP_SYNC_PULSE_FREQUENCY_HZ)) || (p_config->sync_pulse_hz < 1))
    {
        return CTC_E_INVALID_PARAM;
    }

    if (((p_config->sync_pulse_duty > 99) || (p_config->sync_pulse_duty < 1)) && !DRV_IS_AT(lchip))
    {
        return CTC_E_INVALID_PARAM;
    }
    else if (DRV_IS_AT(lchip) && !p_config->sync_pulse_duty)
    {
        return CTC_E_INVALID_PARAM;
    }

    if (((p_config->accuracy > 49) || (p_config->accuracy < 32)) && (p_config->accuracy != 0xFE))
    {
        return CTC_E_INVALID_PARAM;
    }

    if (p_config->epoch > 63)
    {
        return CTC_E_INVALID_PARAM;
    }

    if (p_config->hw_mode)
    {
        if(p_config->mode != CTC_PTP_INTF_MODE_INPUT)
        {
            return CTC_E_INVALID_PARAM;
        }

        if(p_config->drift_time > SYS_PTP_MAX_DRIFT_TIME)
        {
            return CTC_E_INVALID_PARAM;
        }
        /*reset hw_mode=0 when euint image uninstalled*/
        if(!DRV_FROM_AT(lchip))
        {
            CTC_ERROR_RETURN(_sys_usw_ptp_check_ptp_eunit_init(lchip, &value));
            if(!CTC_IS_BIT_SET(value, M_UNTT_SYNC_ENABLE))
            {
                p_config->hw_mode = 0;
            }
        }
    }

    /*the frequency relationship between syncClock and syncPulse must set as follow:
    (1)the frequency of syncClock must be integer multiples of syncPulse
    (2)the period of syncClock must be longer than ( epoch + MCHIP_CAP(SYS_CAP_PTP_SYNC_CODE_BIT) )
    */
    if ((p_config->sync_pulse_hz > p_config->sync_clock_hz)
        || (p_config->sync_clock_hz % p_config->sync_pulse_hz)
        || ((p_config->sync_clock_hz / p_config->sync_pulse_hz) < (p_config->epoch + MCHIP_CAP(SYS_CAP_PTP_SYNC_CODE_BIT))))
    {
        return CTC_E_INVALID_PARAM;
    }

    PTP_LOCK;
    ret = MCHIP_PTP(lchip)->set_sync_intf? MCHIP_PTP(lchip)->set_sync_intf(lchip, (void*)p_config)
    : _sys_usw_ptp_set_sync_intf(lchip, p_config);

    PTP_UNLOCK;

    return ret;
}

/**
 @brief  Get sync interface config
*/
int32
sys_usw_ptp_get_sync_intf(uint8 lchip, ctc_ptp_sync_intf_cfg_t* p_config)
{
    int32 ret = CTC_E_NONE;

    /*check*/
    SYS_PTP_INIT_CHECK();
    CTC_PTR_VALID_CHECK(p_config);
    CTC_MAX_VALUE_CHECK(p_config->domain_id, MCHIP_CAP(SYS_CAP_PTP_MAX_DOMAIN_ID));

    /*debug info*/
    SYS_PTP_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    SYS_PTP_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "Get sync interface config, lchip:%d\n", lchip);

    PTP_LOCK;
    ret = MCHIP_PTP(lchip)->get_sync_intf ? MCHIP_PTP(lchip)->get_sync_intf(lchip, (void*)p_config)
    : _sys_usw_ptp_get_sync_intf(lchip, p_config);
    PTP_UNLOCK;

    return ret;
}

/**
 @brief  Set toggle time to trigger sync interface output syncColck signal
*/
int32
sys_usw_ptp_set_sync_intf_toggle_time(uint8 lchip, ctc_ptp_time_t* p_toggle_time)
{
    int32 ret = CTC_E_NONE;
    uint32 cmd = 0;
    uint32 offset_ns = 0;
    uint32 offset_s = 0;
    TsEngineOffsetAdj_m ptp_offset_adjust;

    /*check*/
    SYS_PTP_INIT_CHECK();
    CTC_PTR_VALID_CHECK(p_toggle_time);

    /*debug info*/
    SYS_PTP_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    SYS_PTP_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "Set sync interface toggle time, lchip:%d, seconds:%d, nanoseconds:%d, nano nanoseconds:%d\n", \
                    lchip, p_toggle_time->seconds, p_toggle_time->nanoseconds, p_toggle_time->nano_nanoseconds);

    if(DRV_FROM_AT(lchip))
    {
        return CTC_E_NOT_SUPPORT;
    }

    /* get offset ts */
    sal_memset(&ptp_offset_adjust, 0, sizeof(ptp_offset_adjust));

    SYS_EUNIT_HW_LOCK(lchip, SYS_EUNIT_M, 0);
    cmd = DRV_IOR(TsEngineOffsetAdj_t, DRV_ENTRY_FLAG);
    DRV_IOCTL(lchip, 0, cmd, &ptp_offset_adjust);
    SYS_EUNIT_HW_UNLOCK(lchip, SYS_EUNIT_M, 0);
    GetTsEngineOffsetAdj(A, offsetNs_f, &ptp_offset_adjust, &offset_ns);
    GetTsEngineOffsetAdj(A, offsetSecond_f, &ptp_offset_adjust, &offset_s);

    if ((p_toggle_time->nanoseconds >= MCHIP_CAP(SYS_CAP_PTP_NS_OR_NNS_VALUE)) ||
        (p_toggle_time->nano_nanoseconds >= MCHIP_CAP(SYS_CAP_PTP_NS_OR_NNS_VALUE)) ||
        (p_toggle_time->seconds < offset_s) ||
        (p_toggle_time->seconds == offset_s && p_toggle_time->nano_nanoseconds < offset_ns))
    {
        return CTC_E_INVALID_PARAM;
    }

    if(p_toggle_time->nanoseconds >= offset_ns)
    {
        p_toggle_time->nanoseconds -= offset_ns;
        p_toggle_time->seconds -= offset_s;
    }
    else
    {
        p_toggle_time->nanoseconds = p_toggle_time->nanoseconds + MCHIP_CAP(SYS_CAP_PTP_NS_OR_NNS_VALUE) - offset_ns;
        p_toggle_time->seconds = p_toggle_time->seconds - offset_s - 1;
    }

    PTP_LOCK;

    ret = _sys_usw_ptp_set_sync_intf_toggle_time(lchip, p_toggle_time);

    PTP_UNLOCK;

    return ret;
}

/**
 @brief  Set toggle time to trigger sync interface output syncColck signal
*/
int32
sys_usw_ptp_get_sync_intf_toggle_time(uint8 lchip, ctc_ptp_time_t* p_toggle_time)
{
    int32 ret = CTC_E_NONE;
    uint32 cmd = 0;
    uint32 offset_ns = 0;
    uint32 offset_s = 0;
    TsEngineOffsetAdj_m ptp_offset_adjust;
    /*check*/
    SYS_PTP_INIT_CHECK();
    CTC_PTR_VALID_CHECK(p_toggle_time);

    /*debug info*/
    SYS_PTP_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    SYS_PTP_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "Get sync interface toggle time, lchip:%d\n", lchip);

    if(DRV_FROM_AT(lchip))
    {
        return CTC_E_NOT_SUPPORT;
    }

    /* get offset ts */
    sal_memset(&ptp_offset_adjust, 0, sizeof(ptp_offset_adjust));
    
    SYS_EUNIT_HW_LOCK(lchip, SYS_EUNIT_M, 0);
    cmd = DRV_IOR(TsEngineOffsetAdj_t, DRV_ENTRY_FLAG);
    DRV_IOCTL(lchip, 0, cmd, &ptp_offset_adjust);
    SYS_EUNIT_HW_UNLOCK(lchip, SYS_EUNIT_M, 0);
    GetTsEngineOffsetAdj(A, offsetNs_f, &ptp_offset_adjust, &offset_ns);
    GetTsEngineOffsetAdj(A, offsetSecond_f, &ptp_offset_adjust, &offset_s);

    PTP_LOCK;

    ret = _sys_usw_ptp_get_sync_intf_toggle_time(lchip, p_toggle_time);

    PTP_UNLOCK;

    if (p_toggle_time->nanoseconds + offset_ns >= MCHIP_CAP(SYS_CAP_PTP_NS_OR_NNS_VALUE))
    {
        p_toggle_time->nanoseconds = p_toggle_time->nanoseconds + offset_ns - MCHIP_CAP(SYS_CAP_PTP_NS_OR_NNS_VALUE);
        p_toggle_time->seconds = p_toggle_time->seconds + offset_s + 1;
    }
    else
    {
        p_toggle_time->nanoseconds += offset_ns;
        p_toggle_time->seconds += offset_s;
    }
    return ret;
}

/**
 @brief  Get sync interface input time information
*/
int32
sys_usw_ptp_get_sync_intf_code(uint8 lchip, ctc_ptp_sync_intf_code_t* g_time_code)
{
    int32 ret = CTC_E_NONE;

    /*check*/
    SYS_PTP_INIT_CHECK();
    CTC_PTR_VALID_CHECK(g_time_code);
    CTC_MAX_VALUE_CHECK(g_time_code->domain_id, MCHIP_CAP(SYS_CAP_PTP_MAX_DOMAIN_ID));

    /*debug info*/
    SYS_PTP_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    SYS_PTP_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "Get sync interface time code, lchip:%d\n", lchip);

    PTP_LOCK;

    ret = _sys_usw_ptp_get_sync_intf_code(lchip, g_time_code);

    PTP_UNLOCK;

    return ret;
}

/**
 @brief  Clear sync interface input time information
*/
int32
sys_usw_ptp_clear_sync_intf_code(uint8 lchip)
{
    int32 ret = CTC_E_NONE;

    /*check*/
    SYS_PTP_INIT_CHECK();

    /*debug info*/
    SYS_PTP_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    SYS_PTP_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "Clear sync interface time code, lchip:%d\n", lchip);

    PTP_LOCK;

    ret = _sys_usw_ptp_clear_sync_intf_code(lchip);

    PTP_UNLOCK;

    return ret;
}

/**
 @brief  Set ToD interface config
*/
int32
sys_usw_ptp_set_tod_intf(uint8 lchip, ctc_ptp_tod_intf_cfg_t* config)
{
    int32 ret = CTC_E_NONE;

    /*check*/
    SYS_PTP_INIT_CHECK();
    CTC_PTR_VALID_CHECK(config);
    CTC_MAX_VALUE_CHECK(config->mode, CTC_PTP_INTF_MODE_MAX - 1);
    CTC_MAX_VALUE_CHECK(config->domain_id, MCHIP_CAP(SYS_CAP_PTP_MAX_DOMAIN_ID));
    if (config->thrd != CTC_MAX_UINT32_VALUE)
    {
        CTC_MAX_VALUE_CHECK(config->thrd, MCHIP_CAP(SYS_CAP_PTP_NS_OR_NNS_VALUE) - 1);
    }

    /*debug info*/
    SYS_PTP_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    SYS_PTP_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "Set tod interface config, lchip:%d\n", lchip);

    if (CTC_PTP_INTF_MODE_INPUT == config->mode || CTC_PTP_INTF_MODE_OUTPUT == config->mode)
    {
        if ((config->pulse_duty > 99) || (config->pulse_duty < 1))
        {
            return CTC_E_INVALID_PARAM;
        }

        if (config->epoch > 0x7FFF)
        {
            return CTC_E_INVALID_PARAM;
        }
    }
    PTP_LOCK;

    SYS_USW_REGISTER_WB_SYNC_EN(lchip, CTC_FEATURE_PTP, SYS_WB_APPID_PTP_SUBID_MASTER, 1);
    ret = _sys_usw_ptp_set_tod_intf(lchip, config);

    PTP_UNLOCK;

    return ret;
}

/**
 @brief  Get ToD interface config
*/
int32
sys_usw_ptp_get_tod_intf(uint8 lchip, ctc_ptp_tod_intf_cfg_t* config)
{
    int32 ret = CTC_E_NONE;

    /*check*/
    SYS_PTP_INIT_CHECK();
    CTC_PTR_VALID_CHECK(config);

    /*debug info*/
    SYS_PTP_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    SYS_PTP_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "Get tod interface config, lchip:%d\n", lchip);

    PTP_LOCK;

    ret = _sys_usw_ptp_get_tod_intf(lchip, config);

    PTP_UNLOCK;

    return ret;
}

/**
 @brief  Add/Set ptp session config
*/
int32
sys_usw_ptp_add_session(uint8 lchip, ctc_ptp_session_t* ptp_session)
{
    int32 ret = CTC_E_NONE;

    SYS_PTP_INIT_CHECK();
    CTC_PTR_VALID_CHECK(ptp_session);

    PTP_LOCK;
    ret = MCHIP_PTP(lchip)->add_session? MCHIP_PTP(lchip)->add_session(lchip, ptp_session) : CTC_E_NOT_SUPPORT;
    PTP_UNLOCK;

    return ret;
}

/**
 @brief  Remove ptp session
*/
int32
sys_usw_ptp_remove_session(uint8 lchip, ctc_ptp_session_t* ptp_session)
{
    int32 ret = CTC_E_NONE;

    SYS_PTP_INIT_CHECK();

    PTP_LOCK;
    ret = MCHIP_PTP(lchip)->remove_session? MCHIP_PTP(lchip)->remove_session(lchip,ptp_session) : CTC_E_NOT_SUPPORT;
    PTP_UNLOCK;

    return ret;
}



/**
 @brief  Get ptp session config
*/
int32
sys_usw_ptp_get_session(uint8 lchip, ctc_ptp_session_t* ptp_session)
{
    int32 ret = CTC_E_NONE;

    SYS_PTP_INIT_CHECK();
    CTC_PTR_VALID_CHECK(ptp_session);
    
    PTP_LOCK;
    ret = MCHIP_PTP(lchip)->get_session_cfg? MCHIP_PTP(lchip)->get_session_cfg(lchip, ptp_session) : CTC_E_NOT_SUPPORT;
    PTP_UNLOCK;
    
    return ret;
}


/**
 @brief  Set ToD interface output message config
*/
int32
sys_usw_ptp_set_tod_intf_tx_code(uint8 lchip, ctc_ptp_tod_intf_code_t* tx_code)
{
    int32 ret = CTC_E_NONE;

    /*check*/
    SYS_PTP_INIT_CHECK();
    CTC_PTR_VALID_CHECK(tx_code);

    /*debug info*/
    SYS_PTP_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    SYS_PTP_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "Set tod interface tx time code, lchip:%d\n", lchip);

    if (tx_code->clock_src > 3)
    {
        return CTC_E_INVALID_PARAM;
    }

    PTP_LOCK;

    ret = _sys_usw_ptp_set_tod_intf_tx_code(lchip, tx_code);

    PTP_UNLOCK;

    return ret;
}

/**
 @brief  Get ToD interface output message config
*/
int32
sys_usw_ptp_get_tod_intf_tx_code(uint8 lchip, ctc_ptp_tod_intf_code_t* tx_code)
{
    int32 ret = CTC_E_NONE;

    /*check*/
    SYS_PTP_INIT_CHECK();
    CTC_PTR_VALID_CHECK(tx_code);

    /*debug info*/
    SYS_PTP_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    SYS_PTP_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "Get tod interface tx time code, lchip:%d\n", lchip);

    PTP_LOCK;

    ret = _sys_usw_ptp_get_tod_intf_tx_code(lchip, tx_code);

    PTP_UNLOCK;

    return ret;
}

/**
 @brief  Get ToD interface input time information
*/
int32
sys_usw_ptp_get_tod_intf_rx_code(uint8 lchip, ctc_ptp_tod_intf_code_t* rx_code)
{
    int32 ret = CTC_E_NONE;

    /*check*/
    SYS_PTP_INIT_CHECK();
    CTC_PTR_VALID_CHECK(rx_code);

    /*debug info*/
    SYS_PTP_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    SYS_PTP_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "Get tod interface rx time code, lchip:%d\n", lchip);

    PTP_LOCK;

    ret = _sys_usw_ptp_get_tod_intf_rx_code(lchip, rx_code);

    PTP_UNLOCK;

    return ret;
}

/**
 @brief  Clear TOD interface input time information
*/
int32
sys_usw_ptp_clear_tod_intf_code(uint8 lchip)
{
    int32 ret = CTC_E_NONE;

    /*check*/
    SYS_PTP_INIT_CHECK();

    /*debug info*/
    SYS_PTP_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    SYS_PTP_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "Clear tod interface rx time code, lchip:%d\n", lchip);

    PTP_LOCK;

    ret = _sys_usw_ptp_clear_tod_intf_code(lchip);

    PTP_UNLOCK;

    return ret;
}

/** @brief  Register TX ts captured callback*/
int32
sys_usw_ptp_set_tx_ts_captured_cb(uint8 lchip, CTC_INTERRUPT_EVENT_FUNC cb)
{
    p_usw_ptp_master[lchip]->g_p_tx_ts_capture_cb = cb;
    return CTC_E_NONE;
}

#define __7_PTP_INIT__
/**
 @brief Initialize PTP module and set ptp default config
*/
int32
sys_usw_ptp_init(uint8 lchip, ctc_ptp_global_config_t* ptp_global_cfg)
{
#ifdef EMULATION_ENV
    //return 0;
#endif
    int32 ret = CTC_E_NONE;
    uint32 cmd = 0;
    uint16 coreclock = 0;
    uint32 field_value = 0;
    IpeIntfMapperCtl_m ipe_intf_mapper_ctl;
    TsEngineRcQuanta_m ptp_frc_quanta;
    TsEngineRefRcCtl_m ptp_frc_ctl;
    TsEngineSyncIntfCfg_m ptp_sync_intf_cfg;
    TsEngineTodCfg_m ptp_tod_cfg;
    TsEngineFifoDepthRecord_m ptp_engine_fifo_depth_record;
    EpeHeaderEditPtpMsgTypeXlateCtl_m ptp_msg_type_ctl;
//    PllTsCfg_m PllTsCfg;
    uintptr chip_id = lchip;
    uint8 index = 0;
    uint8 chip_num =0;

    LCHIP_CHECK(lchip);
    CTC_PTR_VALID_CHECK(ptp_global_cfg);
    CTC_MAX_VALUE_CHECK(ptp_global_cfg->intf_selected,MAX_CTC_PTP_INTF_SELECT);
    CTC_MAX_VALUE_CHECK(ptp_global_cfg->clock_frq,CTC_PTP_CLOCK_FRQ_MAX);

    if (CTC_E_NONE != _sys_usw_ptp_check_ptp_init(lchip))
    {
        return CTC_E_NONE;
    }

    if (p_usw_ptp_master[lchip] != NULL)
    {
        return CTC_E_NONE;
    }
    SYS_VCHIP_MASTER_INIT(lchip, p_usw_ptp_master, CTC_FEATURE_PTP);
    /* create ptp master */
    p_usw_ptp_master[lchip] = (sys_ptp_master_t*)mem_malloc(MEM_PTP_MODULE, sizeof(sys_ptp_master_t));
    if (NULL == p_usw_ptp_master[lchip])
    {
        SYS_PTP_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " No memory \n");
        ret = CTC_E_NO_MEMORY;
        goto error_malloc;
    }

    sal_memset(p_usw_ptp_master[lchip], 0, sizeof(sys_ptp_master_t));

    ret = sal_mutex_create(&p_usw_ptp_master[lchip]->p_ptp_mutex);
    if (ret || !p_usw_ptp_master[lchip]->p_ptp_mutex)
    {
        SYS_PTP_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " Create mutex fail\n");
        ret = CTC_E_NO_MEMORY;
        goto error_mutex;
    }
    if (NULL == p_ptp_cb_mutex)
    {
        ret = sal_mutex_create(&p_ptp_cb_mutex);
        if (ret || !p_ptp_cb_mutex)
        {
            SYS_PTP_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " Create cb mutex fail\n");
            ret = CTC_E_NO_MEMORY;
            goto error_mutex;
        }
    }
    
    /* init ts buffer */
    p_usw_ptp_master[lchip]->p_tx_ts_vector = ctc_vector_init(SYS_PTP_MAX_TX_TS_BLOCK_NUM, SYS_PTP_MAX_TX_TS_BLOCK_SIZE);
    if (NULL == p_usw_ptp_master[lchip]->p_tx_ts_vector)
    {
        SYS_PTP_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " No memory \n");
        ret = CTC_E_NO_MEMORY;
        goto error_tx_ts_vector;
    }

    p_usw_ptp_master[lchip]->p_rx_ts_vector = ctc_vector_init(MAX_CTC_PTP_TIEM_INTF, SYS_PTP_MAX_RX_TS_BLOCK_SIZE);
    if (NULL == p_usw_ptp_master[lchip]->p_rx_ts_vector)
    {
        SYS_PTP_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " No memory \n");
        ret = CTC_E_NO_MEMORY;
        goto error_rx_ts_vector;
    }

    /* set cache aging time */
    p_usw_ptp_master[lchip]->cache_aging_time = ptp_global_cfg->cache_aging_time;

    /*init quanta*/
    CTC_ERROR_GOTO(_sys_usw_ptp_get_quanta(lchip, &(p_usw_ptp_master[lchip]->quanta)), ret, error_ioctl);
    if (0 == p_usw_ptp_master[lchip]->quanta)
    {
        p_usw_ptp_master[lchip]->quanta = MCHIP_CAP(SYS_CAP_PTP_RC_QUANTA);
    }

    sal_memset(&ptp_frc_quanta, 0, sizeof(ptp_frc_quanta));
    if (DRV_IS_DUET2(lchip))
    {
        SetTsEngineRcQuanta(V, quanta_f, &ptp_frc_quanta, p_usw_ptp_master[lchip]->quanta);
    }
    else
    {/*for ctc_ptp_clock_frq_t, used only when use_internal_clock_en set 0 */
        if(DRV_IS_TSINGMA(lchip) && !ptp_global_cfg->use_internal_clock_en)
        {
            if(ptp_global_cfg->clock_frq == CTC_PTP_CLOCK_FRQ_1)
            {
                p_usw_ptp_master[lchip]->quanta = 8;
            }
            else if(ptp_global_cfg->clock_frq == CTC_PTP_CLOCK_FRQ_0)
            {
                p_usw_ptp_master[lchip]->quanta = 10;
            }
        }
        SetTsEngineRcQuanta(V, rcQuanta_f, &ptp_frc_quanta, p_usw_ptp_master[lchip]->quanta);
    }
    cmd = DRV_IOW(TsEngineRcQuanta_t, DRV_ENTRY_FLAG);
    CTC_ERROR_GOTO(DRV_IOCTL(lchip, 0, cmd, &ptp_frc_quanta), ret, error_ioctl);

    /*init ptp register*/
    sal_memset(&ipe_intf_mapper_ctl, 0, sizeof(ipe_intf_mapper_ctl));
    cmd = DRV_IOR(IpeIntfMapperCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_GOTO(DRV_IOCTL(lchip, 0, cmd, &ipe_intf_mapper_ctl), ret, error_ioctl);

    SetIpeIntfMapperCtl(V, ptpUseVlanIndex_f, &ipe_intf_mapper_ctl, 0);
    SetIpeIntfMapperCtl(V, ptpIndexObeyPort_f, &ipe_intf_mapper_ctl, 0);
    cmd = DRV_IOW(IpeIntfMapperCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_GOTO(DRV_IOCTL(lchip, 0, cmd, &ipe_intf_mapper_ctl), ret, error_ioctl);

    /*init sync interface*/
    sal_memset(&ptp_sync_intf_cfg, 0, sizeof(ptp_sync_intf_cfg));
    SetTsEngineSyncIntfCfg(V, syncClockOutEn_f, &ptp_sync_intf_cfg, 1);
    SetTsEngineSyncIntfCfg(V, syncPulseOutEnable_f, &ptp_sync_intf_cfg, 1);
    SetTsEngineSyncIntfCfg(V, syncCodeOutEnable_f, &ptp_sync_intf_cfg, 1);
    SetTsEngineSyncIntfCfg(V, syncPulseInIntrEn_f, &ptp_sync_intf_cfg, 0);
    SetTsEngineSyncIntfCfg(V, ignoreSyncCodeInRdy_f, &ptp_sync_intf_cfg, 0);
    SetTsEngineSyncIntfCfg(V, syncPulseOutNum_f, &ptp_sync_intf_cfg, 0);
    SetTsEngineSyncIntfCfg(V, offsetAdjMode_f, &ptp_sync_intf_cfg, 0);/*0:sw,1:hw*/
    SetTsEngineSyncIntfCfg(V, offsetHwAdjDisperseEn_f, &ptp_sync_intf_cfg, 0);
    if (CTC_PTP_INTF_SELECT_SYNC == ptp_global_cfg->intf_selected)
    {
        SetTsEngineSyncIntfCfg(V, tsCaptureEn_f, &ptp_sync_intf_cfg, 1);
    }
    cmd = DRV_IOW(TsEngineSyncIntfCfg_t, DRV_ENTRY_FLAG);
    CTC_ERROR_GOTO(DRV_IOCTL(lchip, 0, cmd, &ptp_sync_intf_cfg), ret, error_ioctl);

    /*init ToD interface*/
    sal_memset(&ptp_tod_cfg, 0, sizeof(ptp_tod_cfg));
    SetTsEngineTodCfg(V, todCodeOutEnable_f, &ptp_tod_cfg, 1);
    SetTsEngineTodCfg(V, todPulseOutEnable_f, &ptp_tod_cfg, 1);
    SetTsEngineTodCfg(V, todPulseInIntrEn_f, &ptp_tod_cfg, 1);
    SetTsEngineTodCfg(V, ignoreTodCodeInRdy_f, &ptp_tod_cfg, 1);
    SetTsEngineTodCfg(V, todCodeSampleThreshold_f, &ptp_tod_cfg, 7);
    SetTsEngineTodCfg(V, todPulseOutMode_f, &ptp_tod_cfg, 1);
    SetTsEngineTodCfg(V, todPulseOutDelay_f, &ptp_tod_cfg, 0); /* not pre output */
    /*1ms= todPulseReqMaskInterval*512/clockCore(M)/1000*/
    CTC_ERROR_GOTO(sys_usw_get_chip_clock(lchip, &coreclock), ret, error_ioctl);
    field_value = (((uint32)coreclock * (1000000 / DOWN_FRE_RATE)) >> 9) - 100;
    SetTsEngineTodCfg(V, todPulseReqMaskInterval_f, &ptp_tod_cfg, field_value); /* 1ms */
    if (CTC_PTP_INTF_SELECT_TOD == ptp_global_cfg->intf_selected)
    {
        SetTsEngineTodCfg(V, todTsCaptureEn_f, &ptp_tod_cfg, 1);
    }
    cmd = DRV_IOW(TsEngineTodCfg_t, DRV_ENTRY_FLAG);
    CTC_ERROR_GOTO(DRV_IOCTL(lchip, 0, cmd, &ptp_tod_cfg), ret, error_ioctl);

    p_usw_ptp_master[lchip]->intf_selected = ptp_global_cfg->intf_selected;
    p_usw_ptp_master[lchip]->tod_1pps_delay = 0;
    p_usw_ptp_master[lchip]->tod_1pps_delay_nano_ns = 0;

    /*init PllMiscCfg, useless for TM&TMM*/
    field_value = 0;
    cmd = DRV_IOW(PllMiscCfg_t, PllMiscCfg_cfgPllMiscReset_f);
    CTC_ERROR_GOTO(DRV_FIELD_IOCTL(lchip, 0, cmd, &field_value), ret, error_ioctl);

    /*set ts capture ctl*/
    field_value = DRV_FROM_AT(lchip)?(0x1F & (~(1 << SYS_AT_PTP_TIEM_INTF_TOD_1PPS)))
    :(0x1FF & (~(1 << CTC_PTP_TIEM_INTF_TOD_1PPS | 1 << CTC_PTP_TIEM_INTF_SYNC_PULSE)));
    cmd = DRV_IOW(TsEngineTsCaptureCtrl_t, TsEngineTsCaptureCtrl_tsCaptureFifoMask_f);
    CTC_ERROR_GOTO(DRV_FIELD_IOCTL(lchip, 0, cmd, &field_value), ret, error_ioctl);

    /*useless, default value is 1*/
    field_value = 1;
    cmd = DRV_IOW(TsEngineTsCaptureCtrl_t, TsEngineTsCaptureCtrl_tsCaptureFifoIntrThreshold_f);
    CTC_ERROR_GOTO(DRV_FIELD_IOCTL(lchip, 0, cmd, &field_value), ret, error_ioctl);

    /*set ts fifo depth, useless for TM&TMM, read only tbl*/
    sal_memset(&ptp_engine_fifo_depth_record, 0, sizeof(ptp_engine_fifo_depth_record));
    SetTsEngineFifoDepthRecord(V, tsCaptureFifoFifoDepth_f, &ptp_engine_fifo_depth_record, 15);
    cmd = DRV_IOW(TsEngineFifoDepthRecord_t, DRV_ENTRY_FLAG);
    CTC_ERROR_GOTO(DRV_IOCTL(lchip, 0, cmd, &ptp_engine_fifo_depth_record), ret, error_ioctl);

    /*enable FRC counter(useless, default value is the same)*/
    sal_memset(&ptp_frc_ctl, 0, sizeof(ptp_frc_ctl));
    SetTsEngineRefRcCtl(V, rcEn_f, &ptp_frc_ctl, 1);
    SetTsEngineRefRcCtl(V, rcFifoFullThreshold_f, &ptp_frc_ctl, 7);
    cmd = DRV_IOW(TsEngineRefRcCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_GOTO(DRV_IOCTL(lchip, 0, cmd, &ptp_frc_ctl), ret, error_ioctl);

    /*init cfgTsUseIntRefClk */
    if (ptp_global_cfg->use_internal_clock_en)
    {
        field_value = 1;
    }
    else
    {
        field_value = 0;
    }
    if (DRV_IS_DUET2(lchip) || DRV_IS_AT(lchip))
    {
        cmd = DRV_IOW(SupMiscCfg_t, SupMiscCfg_cfgTsUseIntRefClk_f);
        CTC_ERROR_GOTO(DRV_FIELD_IOCTL(lchip, 0, cmd, &field_value), ret, error_ioctl);
    }
    else
    {
        cmd = DRV_IOW(SupDskCfg_t, SupDskCfg_cfgTsUseIntRefClk_f);
        CTC_ERROR_GOTO(DRV_FIELD_IOCTL(lchip, 0, cmd, &field_value), ret, error_ioctl);
    }

    if(!DRV_FROM_TMM(lchip))
    {
        /* support 4ns default use 250Mhz*/
        field_value = 2;
        cmd = DRV_IOW(SupDskCfg_t, SupDskCfg_cfgClkTsRefDiv_f);
        CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &field_value));

        if (DRV_IS_TSINGMA(lchip))
        {
            field_value = 1;
            cmd = DRV_IOW(SupMiscCfg_t, SupMiscCfg_cfgSelMiscB_f);
            CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &field_value));

            field_value = 0;
            cmd = DRV_IOW(SupDskCfg_t, SupDskCfg_cfgTodUseExtRefClk_f);
            CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &field_value));

            field_value = coreclock / 100;
            cmd = DRV_IOW(SupDskCfg_t, SupDskCfg_cfgClkMiscDiv_f);
            CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &field_value));

            field_value = 651;
            cmd = DRV_IOW(SupDskCfg_t, SupDskCfg_cfgClkTodDiv_f);
            CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &field_value));

            field_value = 1;
            cmd = DRV_IOW(SupDskCfg_t, SupDskCfg_cfgResetClkMiscDiv_f);
            CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &field_value));

            field_value = 0;
            cmd = DRV_IOW(SupDskCfg_t, SupDskCfg_cfgResetClkMiscDiv_f);
            CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &field_value));

            field_value = 1;
            cmd = DRV_IOW(SupDskCfg_t, SupDskCfg_cfgResetClkTodDiv_f);
            CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &field_value));

            field_value = 0;
            cmd = DRV_IOW(SupDskCfg_t, SupDskCfg_cfgResetClkTodDiv_f);
            CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &field_value));
        }

        field_value = 1;
        cmd = DRV_IOW(SupDskCfg_t, SupDskCfg_cfgResetClkTsRefDiv_f);
        CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &field_value));
        field_value = 0;
        cmd = DRV_IOW(SupDskCfg_t, SupDskCfg_cfgResetClkTsRefDiv_f);
        CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &field_value));
    }
    else
    {
        if((DRV_IS_TMM(lchip) || DRV_IS_TMG(lchip)))
        {
            PllTsCfg_m PllTsCfg;
            uint32 qm_num = 0;

            /*set ptp clock frq*/
            cmd = DRV_IOR(PllTsCfg_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &PllTsCfg));
            SetPllTsCfg(V,cfgPllTsPllPwd_f,&PllTsCfg,1);
            SetPllTsCfg(V,cfgPllTsReset_f,&PllTsCfg,1);
            SetPllTsCfg(V,cfgPllTsMultInt_f,&PllTsCfg,(ptp_global_cfg->clock_frq == CTC_PTP_CLOCK_FRQ_0) ? 19 : 15);
            SetPllTsCfg(V,cfgPllTsPostDiv_f,&PllTsCfg,1);
            SetPllTsCfg(V,cfgPllTsPreDiv_f,&PllTsCfg,(ptp_global_cfg->clock_frq == CTC_PTP_CLOCK_FRQ_2) ? 1 : 0);
            SetPllTsCfg(V,cfgPllTsSic_f,&PllTsCfg,12);
            SetPllTsCfg(V,cfgPllTsSip_f,&PllTsCfg,6);
            SetPllTsCfg(V,cfgPllTsSgain_f,&PllTsCfg,5);
            SetPllTsCfg(V,cfgPllTsPllPwd_f,&PllTsCfg,0);
            SetPllTsCfg(V,cfgPllTsReset_f,&PllTsCfg,0);
            cmd = DRV_IOW(PllTsCfg_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &PllTsCfg));
            /*dp0 mac0/1:HS mac2/3:CS
             *dp1 mac0/1:HS mac2/3:CS*/
            for(qm_num = 0; qm_num < MCHIP_CAP(SYS_CAP_TXQM_NUM_PER_DP) * MCHIP_CAP(SYS_CAP_DP_MAX_NUM); qm_num++)
            {
                if (DRV_CHIP_SUB_TYPE_4 == DRV_CHIP_SUB_TYPE(lchip) && (qm_num < SYS_PTP_CS_TXQM_NUM_START
                    || (qm_num >= MCHIP_CAP(SYS_CAP_TXQM_NUM_PER_DP) && qm_num < SYS_PTP_CS_TXQM_NUM_START + MCHIP_CAP(SYS_CAP_TXQM_NUM_PER_DP))))
                {
                    continue;
                }
                /*set tx ts fifo depth thrd*/
                field_value = 1;
                cmd = DRV_IOW(McHataTxFifoThrd_t, McHataTxFifoThrd_cfgHataTxCpuFifoIntDepthThrd_f);
                CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, qm_num, cmd, &field_value));

                field_value = 0x7f;
                cmd = DRV_IOW(McHataTxFifoThrd_t, McHataTxFifoThrd_cfgHataTxTsToCpuFifoAFullThrd_f);
                CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, qm_num, cmd, &field_value));

                /*set tx ts fifo timeout*/
                field_value = 1; /*enable*/
                cmd = DRV_IOW(McHataTxCpuFifoTimeOutCfg_t, McHataTxCpuFifoTimeOutCfg_hataTxCpuFifoTimerOutEn_f);
                CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, qm_num, cmd, &field_value));

                field_value = 1000000; /*1ms*/
                cmd = DRV_IOW(McHataTxCpuFifoTimeOutCfg_t, McHataTxCpuFifoTimeOutCfg_hataTxCpuFifoTimerCfg_f);
                CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, qm_num, cmd, &field_value));
            }
        }
        /*map ptp msgtype*/
        sal_memset(&ptp_msg_type_ctl, 0, sizeof(ptp_msg_type_ctl));
        SetEpeHeaderEditPtpMsgTypeXlateCtl(V, g_0_ptpMsgType_f, &ptp_msg_type_ctl, SYS_PTP_MSG_TYPE_SYNC);
        SetEpeHeaderEditPtpMsgTypeXlateCtl(V, g_1_ptpMsgType_f, &ptp_msg_type_ctl, SYS_PTP_MSG_TYPE_DELAY_REQ);
        SetEpeHeaderEditPtpMsgTypeXlateCtl(V, g_2_ptpMsgType_f, &ptp_msg_type_ctl, SYS_PTP_MSG_TYPE_PDELAY_REQ);
        SetEpeHeaderEditPtpMsgTypeXlateCtl(V, g_3_ptpMsgType_f, &ptp_msg_type_ctl, SYS_PTP_MSG_TYPE_PDELAY_RESP);
        cmd = DRV_IOW(EpeHeaderEditPtpMsgTypeXlateCtl_t, DRV_ENTRY_FLAG);
        CTC_ERROR_GOTO(DRV_IOCTL(lchip, 0, cmd, &ptp_msg_type_ctl), ret, error_ioctl);

        /*correctionfield offset*/
        field_value = 0x8;
        cmd = DRV_IOW(EpeHeaderEditTsCtl_t, EpeHeaderEditTsCtl_g0_1_tsRelativeOffset_f);/*CFUPDATE*/
        CTC_ERROR_GOTO(DRV_FIELD_IOCTL(lchip, 0, cmd, &field_value), ret, error_ioctl);

        /*timestamp offset*/
        field_value = 0x24;
        cmd = DRV_IOW(EpeHeaderEditTsCtl_t, EpeHeaderEditTsCtl_g0_3_tsRelativeOffset_f);/*PTPTAMP*/
        CTC_ERROR_GOTO(DRV_FIELD_IOCTL(lchip, 0, cmd, &field_value), ret, error_ioctl);
    }
    if ((SYS_GET_CHIP_VERSION == SYS_CHIP_SUB_VERSION_A) && DRV_IS_TSINGMA(lchip))
    {
        ret = sal_task_create(&(p_usw_ptp_master[lchip]->p_polling_tod), "ctctod",
              SAL_DEF_TASK_STACK_SIZE, SAL_TASK_PRIO_DEF, sys_usw_ptp_polling_tod_code_rdy, (void*)chip_id);
    }
    else
    {
        if(!DRV_FROM_TMM(lchip))
        {
        uint32 cmd = 0;
        uint32 val = 0;

        val = 1;

        cmd = DRV_IOR(EpeHdrProcReserved_t, EpeHdrProcReserved_reserved_f);
        CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &val));
        val |= (1<<0);
        cmd = DRV_IOW(EpeHdrProcReserved_t, EpeHdrProcReserved_reserved_f);
        CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &val));

        cmd = DRV_IOR(EpeHdrEditReserved_t, EpeHdrEditReserved_reserved_f);
        CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &val));
        val |= (1<<0);
        cmd = DRV_IOW(EpeHdrEditReserved_t, EpeHdrEditReserved_reserved_f);
        CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &val));
        }

        (void)sys_usw_interrupt_register_isr(lchip, SYS_INTR_FUNC_PTP_TOD_CODE_IN_RDY, sys_usw_ptp_isr_tod_code_rdy);
    }
    if(DRV_IS_TMG(lchip))
    {
        field_value = 1;
        cmd = DRV_IOW(EpePktProcCtl_t, EpePktProcCtl_ptpSeqFromHdrEn_f);
        CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &field_value));
        cmd = DRV_IOW(EpeHdrAdjustCtl_t, EpeHdrAdjustCtl_ptpSeqFromHdrEn_f);
        CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &field_value));
    }
    (void)sys_usw_interrupt_register_isr(lchip, SYS_INTR_FUNC_PTP_SYNC_CODE_IN_RDY, sys_usw_ptp_isr_sync_code_rdy);
    if (DRV_FROM_AT(lchip))
    {
#if defined E_UNIT && (FEATURE_MODE == 0)
        (void)sys_usw_eunit_regitser_isr(lchip, SYS_EUNIT_ISR_TOD_CODE_READY, sys_usw_ptp_isr_tod_code_rdy_from_mcu);
#endif
        (void)sys_usw_interrupt_register_isr(lchip, SYS_INTR_FUNC_PTP_SYNC_CODE_IN_RDY1, sys_usw_ptp_isr_sync_code_rdy);
        (void)sys_usw_interrupt_register_isr(lchip, SYS_INTR_FUNC_PTP_SYNC_PULSE1, sys_usw_ptp_isr_sync_pulse_in);
    }
    (void)sys_usw_interrupt_register_isr(lchip, SYS_INTR_FUNC_PTP_TOD_PULSE_IN, sys_usw_ptp_isr_tod_pulse_in);
    (void)sys_usw_interrupt_register_isr(lchip, SYS_INTR_FUNC_PTP_SYNC_PULSE_IN, sys_usw_ptp_isr_sync_pulse_in);
    if (DRV_FROM_AT(lchip))
    {
        for(index = SYS_INTR_FUNC_PTP_TX_TS_FIFO_0_START; index <= SYS_INTR_FUNC_PTP_TX_TS_FIFO_1_END; index++)
        {
            (void)sys_usw_interrupt_register_isr(lchip, index, sys_usw_ptp_isr_tx_ts_capture);
        }
    }
    else if(DRV_IS_TMG(lchip))
    {
        (void)sys_usw_mac_register_cb(lchip, SYS_MAC_INTR_TX_TS, sys_tmg_ptp_isr_tx_ts_capture);//GX_TODO
    }
    else
    {
        (void)sys_usw_mac_register_cb(lchip, SYS_MAC_INTR_TX_TS, sys_usw_ptp_isr_tx_ts_capture);
    }

    if (MCHIP_PTP(lchip)->ptp_init)
    {
        CTC_ERROR_GOTO(MCHIP_PTP(lchip)->ptp_init(lchip,(void*)ptp_global_cfg), ret, error_ioctl);
    }
    sys_usw_interrupt_register_flexe_isr(lchip, SYS_INTR_FLEXE_SUB_TYPE_PTP, sys_usw_ptp_isr_flexe_tx_ts_capture);

    if(DRV_FROM_TMM(lchip))
    {
        (void)sys_usw_interrupt_register_isr(lchip, SYS_INTR_FUNC_PTP_TS_CAPTURE_FIFO, sys_usw_ptp_isr_tod_tx_ts_capture);
    }

    if(DRV_IS_TMM(lchip))
    {
        FlexeMgrInterruptFunc_m flexe_inter;

        /*clock reset*/
        field_value = 1;
        cmd = DRV_IOW(CtcMiscCtlReset_t, CtcMiscCtlReset_resetCoreMcuIntf_f);
        CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &field_value));

        cmd = DRV_IOW(CtcMiscCtlReset_t, CtcMiscCtlReset_resetMcu_f);
        CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &field_value));

        field_value = 0;
        cmd = DRV_IOW(CtcMiscCtlReset_t, CtcMiscCtlReset_resetCoreMcuIntf_f);
        CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &field_value));
#ifndef EMULATION_ENV
        /*load image*/
        if (MCHIP_EUNIT(lchip) && MCHIP_EUNIT(lchip)->load_image)
        {
            MCHIP_EUNIT(lchip)->load_image(lchip, SYS_EUNIT_M, NULL);
        }
#endif
        field_value = 0;
        cmd = DRV_IOW(CtcMiscCtlReset_t, CtcMiscCtlReset_resetMcu_f);
        CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &field_value));

    sal_memset(&flexe_inter, 0, sizeof(flexe_inter));

    SetFlexeMgrInterruptFunc(V, funcIntrFlexeTsCaptureAvail_f, &flexe_inter, 1);
    cmd = DRV_IOW(FlexeMgrInterruptFunc_t, DRV_ENTRY_FLAG);
    DRV_IOCTL(lchip, DRV_INS(0, INTR_INDEX_MASK_RESET), cmd, &flexe_inter);
    DRV_IOCTL(lchip, DRV_INS(1, INTR_INDEX_MASK_RESET), cmd, &flexe_inter);

    }
    /* warmboot register */
    CTC_ERROR_GOTO(sys_usw_wb_sync_register_cb(lchip, CTC_FEATURE_PTP, SYS_WB_APPID_PTP_SUBID_MAX,_sys_usw_ptp_wb_sync), ret, error_wb);
    CTC_ERROR_GOTO(sys_usw_dump_db_register_cb(lchip, CTC_FEATURE_PTP, _sys_usw_ptp_dump_db), ret, error_wb);
#if defined E_UNIT && (FEATURE_MODE == 0)
    sys_usw_eunit_regitser_isr(lchip, SYS_EUNIT_ISR_CODE_READY, sys_usw_ptp_isr_tod_code_rdy_from_mcu);
#endif

    /* warmboot data restore */
    if (CTC_WB_ENABLE(lchip) && (CTC_WB_STATUS(lchip) == CTC_WB_STATUS_RELOADING))
    {
        CTC_ERROR_GOTO(_sys_usw_ptp_wb_restore(lchip), ret, error_wb);
    }

    if (CTC_WB_ENABLE(lchip))
    {
        _sys_usw_ptp_wb_init(lchip);
    }
    sys_usw_mchip_set_feature_en(lchip,CTC_FEATURE_PTP);
    return CTC_E_NONE;

error_wb:
error_ioctl:
    ctc_vector_release(p_usw_ptp_master[lchip]->p_rx_ts_vector);
error_rx_ts_vector:
    ctc_vector_release(p_usw_ptp_master[lchip]->p_tx_ts_vector);
error_tx_ts_vector:
    sal_mutex_destroy(p_usw_ptp_master[lchip]->p_ptp_mutex);
    sys_usw_chip_get_active_num(&chip_num);
    if (p_ptp_cb_mutex && (1 == chip_num))
    {
        sal_mutex_destroy(p_ptp_cb_mutex);
        p_ptp_cb_mutex = NULL;
    }
error_mutex:
    mem_free(p_usw_ptp_master[lchip]);
error_malloc:
    return ret;
}

int32
sys_usw_ptp_deinit(uint8 lchip)
{
    uint8 chip_num =0;
    LCHIP_CHECK(lchip);

    if (NULL == p_usw_ptp_master[lchip])
    {
        return CTC_E_NONE;
    }
    SYS_VCHIP_MASTER_DEINIT(lchip, p_usw_ptp_master, CTC_FEATURE_PTP);
    (void)sys_usw_interrupt_register_isr(lchip, SYS_INTR_FUNC_PTP_SYNC_CODE_IN_RDY, NULL);
    (void)sys_usw_interrupt_register_isr(lchip, SYS_INTR_FUNC_PTP_TOD_CODE_IN_RDY, NULL);
    (void)sys_usw_mac_register_cb(lchip, SYS_MAC_INTR_TX_TS, NULL);
    sys_usw_interrupt_register_flexe_isr(lchip, SYS_INTR_FLEXE_SUB_TYPE_PTP, NULL);

    sys_usw_wb_sync_register_cb(lchip, CTC_FEATURE_PTP,0, NULL);
    sys_usw_dump_db_register_cb(lchip, CTC_FEATURE_PTP, NULL);
    /*free rx ts vector*/
    ctc_vector_traverse(p_usw_ptp_master[lchip]->p_rx_ts_vector, (vector_traversal_fn)_sys_usw_ptp_free_node_data, NULL);
    ctc_vector_release(p_usw_ptp_master[lchip]->p_rx_ts_vector);

    /*free tx ts vector*/
    ctc_vector_traverse(p_usw_ptp_master[lchip]->p_tx_ts_vector, (vector_traversal_fn)_sys_usw_ptp_free_node_data, NULL);
    ctc_vector_release(p_usw_ptp_master[lchip]->p_tx_ts_vector);

    if (DRV_FROM_AT(lchip))
    {
        sys_usw_opf_deinit(lchip, p_usw_ptp_master[lchip]->ptp_opf_type);
        if (p_usw_ptp_master[lchip]->session)
        {
            mem_free(p_usw_ptp_master[lchip]->session);
            p_usw_ptp_master[lchip]->session = NULL;
        }
    }

    sal_mutex_destroy(p_usw_ptp_master[lchip]->p_ptp_mutex);
    if (p_usw_ptp_master[lchip]->p_polling_tod)
    {
        sal_task_destroy(p_usw_ptp_master[lchip]->p_polling_tod);
    }
    sys_usw_chip_get_active_num(&chip_num);
    if (p_ptp_cb_mutex && (1 == chip_num))
    {
        sal_mutex_destroy(p_ptp_cb_mutex);
        p_ptp_cb_mutex = NULL;
    }

    mem_free(p_usw_ptp_master[lchip]);
    return CTC_E_NONE;
}

#endif
